【问题标题】:Python pandas: replace values multiple columns matching multiple columns from another dataframePython pandas:替换值多列匹配来自另一个数据帧的多列
【发布时间】:2015-10-23 10:21:21
【问题描述】:

我搜索了很多答案,最接近的问题是Compare 2 columns of 2 different pandas dataframes, if the same insert 1 into the other in 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[['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

谢谢,

斯蒂芬

【问题讨论】:

  • "我只需要在 df1[[ 'chr', 'pos']] 匹配 df2[['OCHR', 'OSTOP']]" 这不是说只有在 charpos 在df1 在 df2 中匹配 OCHROSTOP
  • 如果合并 chr,ochr 和 pos,ostop,那么就不需要更新了。也许你的意思是更新 chr->CHR 和 post->STOP ?
  • 这就是您的示例中的情况,合并后,您想要更新 df1.chr -> df2.CHR 和 df1.pos -> df2.STOP,如果是错字,可能会更正
  • 这可以在 SQL 更新连接查询的一行中完成。如果您的 dfs 来自数据库,请考虑 SQL 关系引擎的强大功能。
  • @Alexander,不完全是,当 df1 中的 chr 和 pos 与 df2 中的 OCHR 和 OSTOP 匹配时,所有三列(snp、chr 和 pos)都需要更新。

标签: python pandas


【解决方案1】:

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

【讨论】:

  • 你好建勋,看起来很有趣,我从来没有使用过多个索引。在您的示例中,如果我要使用 x1 = df1.set_index(['chr', 'pos'])['snp', 'chr', 'pos'] x2 = df2,它只会更新 'snp' 列。 set_index(['OCHR', 'OSTOP'])['ID', 'CHR', 'STOP'] 在调用 x1.update(x2) 时会更新所有三列吗? (我不明白为什么不)非常感谢。
  • 绝对精彩
【解决方案2】:

首先重新命名要在 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

终于更新(见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(...

【讨论】:

  • 非常感谢,我显然需要阅读更新功能,它看起来非常有用。
猜你喜欢
  • 2016-11-22
  • 2019-07-10
  • 2020-12-02
  • 1970-01-01
  • 1970-01-01
  • 2016-03-29
  • 2016-07-05
  • 1970-01-01
  • 2019-01-02
相关资源
最近更新 更多