2017-07-20 55 views
1

我有一個DF如下:同時更換多個列的內容爲多個條件

CHROM  POS SRR4216489    SRR4216675     SRR4216480 
0  1 127536  ./.      ./.       ./. 
1  1 127573  ./.      0/1:0,5:5:0:112,1,10  ./. 
2  1 135032  ./.      1/1:13,0:13:3240:0,30,361 0/0:13,0:13:3240:0,30,361 
3  1 135208  ./.      0/0:5,0:5:3240:0,20,160  0/1:5,0:5:3240:0,20,160 
4  1 138558  1/1:5,0:5:3240:0,29,177 0/0:0,5:5:0:112,1,10  ./. 

我想換成根據某些條件的樣品列的內容。樣本列是SRR4216489,SRR4216675,SRR4216480。我正在尋找替換'./。'與0.5,任何與0/0開始0.0和任何與0/1或1/1與1.0。我明白這涉及到幾個過程,其中大部分我都可以獨立完成,但我不知道將它們綁定在一起的語法。例如,我可以對樣品SRR4216480做到這一點:

df['SRR4216675'][df.SRR4216675 == './.'] = 0.5 

這種運作良好,courtesy of here,但我不知道如何將它同時適用於所有樣品列。我認爲通過使用循環:

sample_cols = df.columns[2:] 
for s in sample_cols: 
    df[s][df.s =='./.'] = 0.5 

但是這首先似乎並不十分pandonic,它也不會接受來自列表中「df.s」字符串反正。

下一個挑戰是如何解析填充樣本列其他部分的變量字符串。我已經使用分割功能的嘗試:

df=df['SRR4216675'][df.SRR4216675.split(':') == '0/0' ] = 0.0 

,但我得到:

TypeError: 'float' object is not subscriptable 

我相信,一個好辦法,這將是使用Lambda如this但作爲新來大熊貓解決和lambda表達式我發現它非常棘手,我在這裏:

col=df['SRR4216675'][df.SRR4216675.apply(lambda x: x.split(':')[0])] 

,它看起來像它的幾乎沒有,但需要進一步的處理,以取代的價值,也是它看起來像它有2列的ð不會讓我重新整合入現有的DF:

SRR4216675 
./. NaN 
0/1 NaN 
1/1 NaN 
0/0 NaN 
0/0 NaN 

df['SRR4216675'] = col 

ValueError: cannot reindex from a duplicate axis 

我明白,這是在1幾個問題,但我是新來的熊貓和真的很想去處理它。我可以使用基本列表和循環來解決這些問題,這些列表使用Python標準列表,迭代和字符串解析函數,但是在規模上,這將非常慢,因爲我的全尺寸df是數百萬行,包含超過500個樣本列。

+0

查找到熊貓系列和成'pd.Series.replace()'方法的各種'.str'方法。例如:'df.loc [:, ['SRR4216489','SRR4216675','SRR4216480']]。replace(「./。」,0.5,inplace = True)' – Jakub

回答

1

您可以通過使用df.apply和定義一個函數,這樣做:

In [10]: cols = ('SRR4216675', 'SRR4216480', 'SRR4216489') 

In [11]: def replace_vals(row): 
    ...:  for col in cols: 
    ...:   if row[col] == './.': 
    ...:    row[col] = 0.5 
    ...:   elif row[col].startswith('0/0'): 
    ...:    row[col] = 0 
    ...:   elif row[col].startswith('0/1') or row[col].startswith('1/1'): 
    ...:    row[col] = 1 
    ...:  return row 
    ...: 
    ...: 

In [12]: df.apply(replace_vals, axis=1) 
Out[12]: 
    CHROM  POS SRR4216480 SRR4216489 SRR4216675 
0  1 127536   0.5   0.5   0.5 
1  1 127573   0.5   0.5   1.0 
2  1 135032   0.0   0.5   1.0 
3  1 135208   1.0   0.5   0.0 
4  1 138558   0.5   1.0   0.0 

而這裏要做到這一點更快的方法:

首先,讓我們創建一個更大的數據幀,從而我們可以有意義地衡量時間差異,讓我們導入一個計時器,以便我們可以進行測量。

In [70]: from timeit import default_timer as timer 

In [71]: long_df = pd.DataFrame() 

In [72]: for i in range(10000): 
    ...:  long_df = pd.concat([long_df, df]) 

使用我們上面定義的函數,我們得到:

In [76]: start = timer(); long_df.apply(replace_vals, axis=1); end = timer() 

In [77]: end - start 
Out[77]: 8.662535898998613 

現在,我們定義了一個新的功能(計時的目的很容易),我們遍歷列,並應用相同的替換邏輯上面,除了我們使用矢量str.startswith方法對每一列做:

In [78]: def modify_vectorized(): 
    ...:  start = timer() 
    ...:  for col in cols: 
    ...:   long_df.loc[long_df[col] == './.', col] = 0.5 
    ...:   long_df.loc[long_df[col].str.startswith('0/0', na=False), col] = 0 
    ...:   long_df.loc[long_df[col].str.startswith('0/1', na=False), col] = 1 
    ...:   long_df.loc[long_df[col].str.startswith('1/1', na=False), col] = 1 
    ...:  end = timer() 
    ...:  return end - start 

我們重建的大數據幀,我們在其上運行的新功能,讓一個顯著加速:

In [79]: long_df = pd.DataFrame() 

In [80]: for i in range(10000): 
    ...:  long_df = pd.concat([long_df, df]) 
    ...: 

In [81]: time_elapsed = modify_vectorized() 

In [82]: time_elapsed 
Out[82]: 0.44004046998452395 

生成的數據幀是這樣的:

In [83]: long_df 
Out[83]: 
    CHROM  POS SRR4216480 SRR4216489 SRR4216675 
0  1 127536  0.5  0.5  0.5 
1  1 127573  0.5  0.5   1 
2  1 135032   0  0.5   1 
3  1 135208   1  0.5   0 
4  1 138558  0.5   1   0 
0  1 127536  0.5  0.5  0.5 
1  1 127573  0.5  0.5   1 
2  1 135032   0  0.5   1 
3  1 135208   1  0.5   0 
4  1 138558  0.5   1   0 
0  1 127536  0.5  0.5  0.5 
1  1 127573  0.5  0.5   1 
2  1 135032   0  0.5   1 
3  1 135208   1  0.5   0 
4  1 138558  0.5   1   0 
0  1 127536  0.5  0.5  0.5 
... 
+0

感謝你們,我該如何自動提供在列中呢?如果我嘗試爲該函數添加列的參數,那麼在調用該函數時將該參數提供給該函數不起作用? – user3062260

+0

更新了我的答案,使您想修改的列更通用。 – LateCoder

+0

非常感謝!這個解決方案的工作原理,雖然任何進一步的建議,以加快它會很大,但不是必要的。花了大約5分鐘跑過1號染色體,但我可以活下去(有24條染色體可以運行)。再次感謝! – user3062260