1

4 列のタブ区切りファイルがあります。「col1」と「col2」の一意の値のペアごとに「col3」と「col4」を組み合わせる必要があります。例と出力を以下に示します。

私が考えている 1 つの方法は、ネストされたループを使用することです。外側のループは行を順番に読み取り、内側のループは最初からすべての行を読み取り、マップを探します。ただし、このプロセスは計算量が多いようです。

これを行う別の方法はありますか。

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」で入れ替わると、値が結合されます。

4

2 に答える 2

3

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 のリストを で結合し、','で一意にしsetsorted適切に並べ替えます)

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-23T14:39:21.750 に答える
2

@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) 最初の 2 つの列を にe cなるように並べ替え、(2)とc eで用語をグループ化し、次に集約 ( )し、平坦化された用語の並べ替えられたセットをコンマ結合することです。colcol 2aggcol3col4

groupbyこのようなものには本当に便利です。どこかに潜んでいる関数の組み込みの代替品もあるかもしれませんが、join_stringsよくわかりません。

于 2012-10-23T16:09:21.453 に答える