我有一个以制表符分隔的四列文件。我需要为“col1”和“col2”中的每个唯一值对组合“col3”和“col4”。示例和输出如下所示。
我考虑的一种方法是使用嵌套循环:外部循环按顺序读取行,内部循环从头开始读取所有行并查找map。然而,这个过程似乎是计算密集型的。
有没有其他方法可以做到这一点。
col1 col2 col3 col4
a c 1,2 physical
a c 2,3 genetic
b c 22 physical
b d 33,44 genetic
c e 1,2 genetic
c e 2 physical
c f 33,44 physical
c f 3 genetic
a a 4 genetic
e c 1,2 xxxxx
col1 col2 col3 col4
a c 1,2,3 genetic,physical
a a 4 genetic
b c 22 physical
b d 33,44 genetic
c e 1,2 genetic,physical,xxxxx
c f 3,33,44 genetic,physical如果'col1‘和'col2’按照上面最后一行中的值'xxxxx‘进行切换,它将值组合在一起。
发布于 2012-10-23 22:39:22
我将创建一个键的字典,这些键是保存column1和column2数据的元组。这些值将是一个包含column3和column4数据的列表...
from collections import defaultdict
with open('test.dat') as f:
data = defaultdict( lambda:([],[]))
header = f.readline()
for line in f:
col1,col2,col3,col4 = line.split()
col3_data,col4_data = data[(col1,col2)] #data[frozenset((col1,col2))] if order doesn't matter
col3_data.append(col3)
col4_data.append(col4)现在排序并写入输出(使用','连接column3和column4列表,使set和sorted具有唯一性,以便正确排序)
with open('outfile.dat','w') as f:
f.write(header)
#If you used a frozenset in the first part, you might want to do something like:
#for k in sorted(map(sorted,data.keys())):
for k in sorted(data.keys()):
col1,col2 = k
col3_data,col4_data = data[k]
col3_data = ','.join(col3_data) #join the list
col3_data = set(int(x) for x in col3_data.split(',')) #make unique integers
col3_str = ','.join(map(str,sorted(col3_data))) #sort, convert to strings and join with ','
col4_data = ','.join(col4_data) #join the list
col4_data = sorted(set(col4_data.split(','))) #make unique and sort
f.write('{0}\t{1}\t{2}\t{3}\n'.format(col1,col2,col3_str,','.join(col4_data)))发布于 2012-10-24 00:09:21
@mgilson给出了一个很好的不需要额外部件的解决方案(+1)。我看到pandas也被标记了,所以为了完整起见,我将给出一个等价的pandas:
import pandas as pd
df = pd.read_csv("merge.csv",delimiter=r"\s*")
key_cols = ["col1", "col2"]
df[key_cols] = df[key_cols].apply(sorted, axis=1)
def join_strings(seq, key):
vals = [term for entry in seq for term in entry.split(',')]
return ','.join(sorted(set(vals), key=key))
new_df = df.groupby(key_cols).agg({"col3": lambda x: join_strings(x, int),
"col4": lambda x: join_strings(x, str)})
new_df.to_csv("postmerged.csv")它会产生
In [173]: !cat postmerged.csv
col1,col2,col3,col4
a,a,4,genetic
a,c,"1,2,3","genetic,physical"
b,c,22,physical
b,d,"33,44",genetic
c,e,"1,2","genetic,physical,xxxxx"
c,f,"3,33,44","genetic,physical"所做的全部工作是(1)对前两列进行排序,使e c变为c e,(2)按col和col 2对术语进行分组,然后通过逗号连接排序后的平面化术语集来聚合(agg) col3和col4。
对于这样的事情,groupby真的很方便。join_strings函数可能也有一个内置的替代品,但我不确定。
https://stackoverflow.com/questions/13032834
复制相似问题