2017-07-20 26 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