[英]pandas DataFrame: replace values in multiple columns with the value from another
[英]Python pandas: replace values multiple columns matching multiple columns from another dataframe
我搜索了很多答案,最接近的问题是比较两个不同的pandas数据帧的2列,如果相同的插入1到另一个在Python ,但这个人的特定问题的答案是一个简单的合并,它没有回答这个问题一般来说。
我有两个大型数据帧,df1(通常约为1000万行)和df2(约1.3亿行)。 我需要根据匹配两个df2列的两个df1列,使用三列df2中的值更新三列df1中的值。 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等)
df2
ID CHR STOP OCHR OSTOP
rs376643643 1 10040 1 10020
rs373328635 1 10066 1 10056
rs62651026 1 10208 1 10108
rs376007522 1 10209 1 10109
rs368469931 3 30247 1 10139
只有当df1 [['chr','pos']]时,我需要用df2 [['ID','OCHR','OSTOP']]更新df1中的''snp','chr','pos']匹配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
我使用merge作为解决方法:
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
谢谢,
斯特凡
您可以使用update
功能(需要设置匹配条件以进行索引)。 我修改了您的示例数据以允许一些不匹配。
# 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
首先在df2中重新想要合并的列
df2.rename(columns={'OCHR':'chr','OSTOP':'pos'},inplace=True)
现在合并这些列
df_merged = pd.merge(df1, df2, how='inner', on=['chr', 'pos']) # you might have to preserve the df1 index at this stage, not sure
接下来,你想要
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
最后更新(见此链接底部):
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_updater.re_index(...
之前df1.update(df1_updater)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.