Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 熊猫在多个条件下一次替换多个列的内容_Python_Pandas_Dataframe - Fatal编程技术网

Python 熊猫在多个条件下一次替换多个列的内容

Python 熊猫在多个条件下一次替换多个列的内容,python,pandas,dataframe,Python,Pandas,Dataframe,我的df如下所示: CHROM POS SRR4216489 SRR4216675 SRR4216480 0 1 127536 ./. ./. ./. 1 1 127573 ./. 0/1:0,5:5:0:112,1,10 ./. 2

我的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
这很有效,但我不确定如何将其同时应用于所有样本列。我想通过以下方式使用循环:

sample_cols = df.columns[2:]
for s in sample_cols:
    df[s][df.s =='./.'] = 0.5
但这首先看起来不是很泛音,而且它也不接受'df.s'列表中的字符串

下一个挑战是如何解析填充样本列其他部分的变量字符串。我已尝试使用拆分功能:

df=df['SRR4216675'][df.SRR4216675.split(':') == '0/0' ] = 0.0
但我得到:

TypeError: 'float' object is not subscriptable
我确信解决这一问题的一个好方法是使用lambda,例如,但作为熊猫和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中的几个问题,但我对熊猫还不熟悉,我真的很想解决它。我可以使用pythons标准列表、迭代和字符串解析函数的基本列表和循环来解决这些问题,但在规模上,这将非常缓慢,因为我的全尺寸df有数百万行长,包含500多个样本列。

您可以使用
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
...

查看pandas系列中的各种
.str
方法和
pd.series.replace()
方法。例如:
df.loc[:,['SRR4216489','SRR4216675','SRR4216480']].replace(“./”,0.5,inplace=True)
谢谢你的帮助,我怎么能自动输入列呢?如果我尝试向函数中添加列的参数,然后在调用该函数时将该参数提供给该函数,则该函数无效?更新了我的答案,使您要修改的列更加通用。非常感谢!这个解决方案是可行的,尽管任何进一步的加速建议都是很好的,但不是必需的。我花了大约5分钟的时间来检查一条染色体,但我可以接受(检查有24条染色体)。再次感谢!更新了一个明显更快的选项。希望有帮助!