2017-03-01 69 views
2

的程序,我有工作輸出結果outputed製表符分隔的文件看起來像這樣:使用熊貓下令每隔兩行

marker A B C 
Bin_1 1 2 1 
marker C G H B T 
Bin_2 3 1 1 1 2 
marker B H T Z Y A C 
Bin_3 1 1 2 1 3 4 5 

我想,這樣它看起來像這樣來解決它:

marker A B C G H T Y Z 
Bin_1 1 2 1 0 0 0 0 0 
Bin_2 0 1 3 1 1 1 0 0 
Bin_3 4 1 5 0 1 2 3 1 

這是我迄今爲止

import pandas as pd 
from collections import OrderedDict 
df = pd.read_csv('markers.txt',header=None,sep='\t') 
x = map(list,df.values) 
list_of_dicts = [] 
s = 0 
e =1 
g = len(x)+1 
while e < g: 
    new_dict = OrderedDict(zip(x[s],x[e])) 
    list_of_dicts.append(new_dict) 
    s += 2 
    e += 2 

起初,我將這些以字典,然後WA我們要做一些計數並重新創建一個數據框,但這似乎需要花費大量的時間和內存來完成一項簡單的任務。任何建議,以更好的方式來解決這個問題?

回答

3
lines = [str.strip(l).split() for l in open('markers.txt').readlines()] 
dicts = {b[0]: pd.Series(dict(zip(m[1:], b[1:]))) 
     for m, b in zip(lines[::2], lines[1::2])} 
pd.concat(dicts).unstack(fill_value=0) 

     A B C G H T Y Z 
Bin_1 1 2 1 0 0 0 0 0 
Bin_2 0 1 3 1 1 2 0 0 
Bin_3 4 1 5 0 1 2 3 1 
0

不是世界上最優雅的事情,但...

headers = df.iloc[::2][0].apply(lambda x: x.split()[1:]) 
data = df.iloc[1::2][0].apply(lambda x: x.split()[1:]) 

result = [] 
for h, d in zip(headers.values, data.values): 
    result.append(pd.Series(d, index=h)) 
pd.concat(result, axis=1).fillna(0).T 

    A B C G H T Y Z 
0 1 2 1 0 0 0 0 0 
1 0 1 3 1 1 2 0 0 
2 4 1 5 0 1 2 3 1 
1

的觀點是,當你「追加」 DataFrames,結果是與被列聯盟列的數據幀,與NaN或任何在洞中。所以:

$ cat test.py 
import pandas as pd 

frame = pd.DataFrame() 
with open('/tmp/foo.tsv') as markers: 
    while True: 
     line = markers.readline() 
     if not line: 
      break 
     columns = line.strip().split('\t') 
     data = markers.readline().strip().split('\t') 
     new = pd.DataFrame(data=[data], columns=columns) 
     frame = frame.append(new) 

frame = frame.fillna(0) 

print(frame) 
$ python test.py < /tmp/foo.tsv 
    A B C G H T Y Z marker 
0 1 2 1 0 0 0 0 0 Bin_1 
0 0 1 3 1 1 2 0 0 Bin_2 
0 4 1 5 0 1 2 3 1 Bin_3 

如果你不在其他地方使用熊貓,那麼這可能(或可能不會)是矯枉過正。但如果你已經在使用它,那麼我認爲這是完全合理的。

0

爲什麼不將數據處理成輸入一個字典,然後構建DataFrame

>>> with open(...) as f: 
...  d = {} 
...  for marker, bins in zip(f, f): 
...   z = zip(h.split(), v.split()) 
...   _, bin = next(z) 
...   d[bin] = dict(z) 
>>> pd.DataFrame(d).fillna(0).T 
     A B C G H T Y Z 
Bin_1 1 2 1 0 0 0 0 0 
Bin_2 0 1 3 1 1 2 0 0 
Bin_3 4 1 5 0 1 2 3 1 

如果你真的需要軸名稱的列:

>>> pd.DataFrame(d).fillna(0).rename_axis('marker').T 
marker A B C G H T Y Z 
Bin_1 1 2 1 0 0 0 0 0 
Bin_2 0 1 3 1 1 2 0 0 
Bin_3 4 1 5 0 1 2 3 1