Python pandas:替换多个与另一个datafram中的多个列匹配的值

2024-10-01 13:27:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我搜索了很多答案,最接近的问题是Compare 2 columns of 2 different pandas dataframes, if the same insert 1 into the other in Python,但是这个人的特定问题的答案是一个简单的合并,它没有以一般的方式回答这个问题。在

我有两个大数据帧,df1(通常大约1000万行)和df2(大约1.3亿行)。我需要根据两个df1列与两个df2列相匹配的两个df1列,用df2的三列中的值更新值。df1的顺序必须保持不变,并且只有具有匹配值的行才被更新。在

数据帧如下所示:

df1

chr    snp  x    pos a1 a2
1  1-10020  0  10020  G  A    
1  1-10056  0  10056  C  G    
1  1-10108  0  10108  C  G
1  1-10109  0  10109  C  G    
1  1-10139  0  10139  C  T

请注意,“snp”的值并不总是chr pos,它可以接受许多其他值,而没有任何列的链接(如rs1234、indel-6032等)

^{pr2}$

我需要在df1中用df2[['ID','OCHR','OSTOP']]更新df1中的['snp','chr','pos']]仅当df1[['chr','OSTOP']]匹配df2['OCHR','OSTOP']]

所以在这种情况下,在更新之后,df1看起来像:

chr       snp  x     pos a1 a2    
1  rs376643643  0  10040  G  A    
1  rs373328635  0  10066  C  G    
1  rs62651026   0  10208  C  G    
1  rs376007522  0  10209  C  G    
3  rs368469931  0  30247  C  T

我使用合并作为解决方法:

df1 = pd.merge(df1, df2, how='left', left_on=["chr", "pos"], right_on=["OCHR", "OSTOP"],
                                     left_index=False, right_index=False, sort=False)

然后呢

df1.loc[~df1.OCHR.isnull(), ["snp", "chr", "pos"]] = df1.loc[~df1.OCHR.isnull(), ["ID", "CHR", "STOP"]].values

然后删除多余的列。在

是的,这是可行的,但是有什么方法可以直接通过比较两个数据帧的值来实现这一点,我只是不知道如何表述它,而且我在任何地方都找不到答案;我想在这个问题上得到一个普遍的答案可能是有用的。在

我试过了,但没用:

df1.loc[(df1.chr==df2.OCHR) & (df1.pos==df2.OSTOP),["snp", "chr", "pos"]] = df2.loc[df2[['OCHR', 'OSTOP']] == df1.loc[(df1.chr==df2.OCHR) & (df1.pos==df2.OSTOP),["chr", "pos"]],['ID', ''CHR', 'STOP']].values

谢谢

斯蒂芬


Tags: the数据答案posidfalsea1left
2条回答

首先重新命名要在df2中合并的列

df2.rename(columns={'OCHR':'chr','OSTOP':'pos'},inplace=True)

现在合并这些列

^{pr2}$

接下来,你想

updater = df_merged[['D','CHR','STOP']] #this will be your update frame
updater.rename( columns={'D':'snp','CHR':'chr','STOP':'pos'},inplace=True) # rename columns to update original

最后更新(见this link底部):

df1.update( df1_updater) #updates in place
#  chr          snp  x    pos a1 a2
#0   1  rs376643643  0  10040  G  A
#1   1  rs373328635  0  10066  C  G
#2   1   rs62651026  0  10208  C  G
#3   1  rs376007522  0  10209  C  G
#4   3  rs368469931  0  30247  C  T

更新是通过匹配索引/列来工作的,因此您可能必须在整个进程中沿着df1的索引字符串,然后在df1.update(df1_updater)之前执行df1_updater.re_index(...

您可以使用update函数(需要将匹配条件设置为index)。我修改了你的样本数据,允许有一些不匹配。在

# your data
# =====================
# df1 pos is modified from 10020 to 10010
print(df1)

   chr      snp  x    pos a1 a2
0    1  1-10020  0  10010  G  A
1    1  1-10056  0  10056  C  G
2    1  1-10108  0  10108  C  G
3    1  1-10109  0  10109  C  G
4    1  1-10139  0  10139  C  T

print(df2)

            ID  CHR   STOP  OCHR  OSTOP
0  rs376643643    1  10040     1  10020
1  rs373328635    1  10066     1  10056
2   rs62651026    1  10208     1  10108
3  rs376007522    1  10209     1  10109
4  rs368469931    3  30247     1  10139

# processing
# ==========================
# set matching columns to multi-level index
x1 = df1.set_index(['chr', 'pos'])['snp']
x2 = df2.set_index(['OCHR', 'OSTOP'])['ID']
# call update function, this is inplace
x1.update(x2)
# replace the values in original df1
df1['snp'] = x1.values
print(df1)

   chr          snp  x    pos a1 a2
0    1      1-10020  0  10010  G  A
1    1  rs373328635  0  10056  C  G
2    1   rs62651026  0  10108  C  G
3    1  rs376007522  0  10109  C  G
4    1  rs368469931  0  10139  C  T

相关问题 更多 >