【问题标题】:Pandas - Update/Merge 2 Dataframes based on multiple matching column valuesPandas - 基于多个匹配列值更新/合并 2 个数据框
【发布时间】:2020-11-30 11:20:55
【问题描述】:

我有 2 个数据框 left_dfright-df,它们都有 20 个具有相同名称和数据类型的列。 right_df 还增加了 2 列,每行都有唯一值。

我想用来自left_df 的所有值更新right_df 中的行,其中列子集matching_cols = ['col_1', 'col_3', 'col_10', 'col_12'] 的所有列中的值在两个数据帧中都是相同的。 right_df 中另外 2 个唯一列中的值应保留。

理想情况下,我还想在同一命令中从left_df 中删除这些行,或者如果这不可能,则作为下一个命令。我需要多次执行此过程,匹配几个不同的列列表,left_df 在每个循环中删除匹配的行,直到最终找不到更多匹配。

可接受的替代方法是创建一个新数据框new_df 的任何方法,其中包含列表matching_cols 中所有指定列匹配的行集,前20 列中的值来自left_df,值来自@ 987654333@ 在其余 2 列中。

我不关心在任一数据帧中的任何位置保留索引,我在此之后将它们导入 SQL,并将在最后的 2 个 right_df 值之一上重新索引它们。

Pandas 新手,无法确定使用什么方法,尝试了.merge.join.update 等的变体,但似乎无法指定仅在我想要的列值全部更新时更新匹配,或者如何删除这些行/将它们导出到新的 df。

更新:在下面添加了伪代码:

对于left_df 为:

left_df = pd.DataFrame({
   'col_0': ['0', '1', '2', '3', '4', '5'],
   'col_1': ['A', 'B', 'C', 'D', 'E', 'F'],
   'col_2': ['new', 'new', 'new', 'new', 'new', 'new'],
   'col_3': ['new', 'new', 'new', 'new', 'new', 'new'],
   'col_4': ['new', 'new', 'new', 'new', 'new', 'new'],
   'col_5': ['new', 'new', 'new', 'new', 'new', 'new'],
   'col_6': ['new', 'new', 'new', 'new', 'new', 'new'],
   'col_7': ['new', 'new', 'new', 'new', 'new', 'new'],                
  })

和 right_df 为:

right_df = pd.DataFrame({
   'col_0': ['0', '1', '2', '3', '4', '5'],
   'col_1': ['A', 'B', 'C', 'X', 'E', 'F'],
   'col_2': ['old', 'old', 'old', 'old', 'old', 'old'],
   'col_3': ['old', 'old', 'old', 'old', 'old', 'old'],
   'col_4': ['old', 'old', 'old', 'old', 'old', 'old'],
   'col_5': ['old', 'old', 'old', 'old', 'old', 'old'],
   'col_6': ['old', 'old', 'old', 'old', 'old', 'old'],
   'col_7': ['old', 'old', 'old', 'old', 'old', 'old'],
   'col_8': ['uid_0', 'uid_1', 'uid_2', 'uid_3', 'uid_4', 'uid_5'],
   'col_9': ['uid_a', 'uid_b', 'uid_c', 'uid_d', 'uid_e', 'uid_f'],                
  })

在哪里matching_cols = ['col_0', 'col_1']

我想在right_df 上获得以下结果作为新数据帧或就地(注意col_1 与第 3 行不匹配,因此不会更改)

  col_0 col_1 col_2 col_3 col_4 col_5 col_6 col_7  col_8  col_9
0     0     A   new   new   new   new   new   new  uid_0  uid_a
1     1     B   new   new   new   new   new   new  uid_1  uid_b
2     2     C   new   new   new   new   new   new  uid_2  uid_c
3     3     X   old   old   old   old   old   old  uid_3  uid_d
4     4     E   new   new   new   new   new   new  uid_4  uid_e
5     5     F   new   new   new   new   new   new  uid_5  uid_f

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    感谢this post 和 Pandas 文档:

    首先,这是我需要的.merge,我将后缀指定为'_r',仅用于从right_df / 复制我正在更新的旧值的列:

    merged_df = pd.merge(left_df, right_df, on=['col_0', 'col_1'], suffixes=(None, '_r'))
    

    这会产生一个新的数据框,其行包含新列和旧列,仅适用于每个数据框中 on=['col_0', 'col_1'] 列中的值匹配的行。然后我通过对文本'_r' 使用正则表达式过滤器删除“旧”列:

    merged_df.drop(list(merged_df.filter(regex = '_r')), axis=1, inplace=True)
    

    这会产生一个只有“修改”行而没有未修改行的数据框,这对于我的需要来说已经足够接近了。

      col_0 col_1 col_2 col_3 col_4 col_5 col_6 col_7  col_8  col_9
    0     0     A   new   new   new   new   new   new  uid_0  uid_a
    1     1     B   new   new   new   new   new   new  uid_1  uid_b
    2     2     C   new   new   new   new   new   new  uid_2  uid_c
    3     4     E   new   new   new   new   new   new  uid_4  uid_e
    4     5     F   new   new   new   new   new   new  uid_5  uid_f
    

    【讨论】:

      【解决方案2】:

      试试这个

      new_df=pd.concat([left_df,right_df.iloc[:,-1:-3]],axis=1)
      
      

      【讨论】:

      • 这里的.iloc[:,-1:-3]指的是什么?
      • 更新:试过了,它可以工作,但这省略了我需要从right_df 包含在结果中的两列。
      • .iloc[:,-1:-3] 是数据框中列的索引如果您需要特定列,您也可以尝试.loc[:,['list of columns seperated by commas in quotes']] 这肯定会解决所有问题
      • 我刚才看到了你所做的编辑,我认为是above answer will do work (.loc) ,因为这是我可能想到的唯一正确的方法来连接数据```你必须正确指定名称` ` in loc .....请尝试删除数据中出现的两次col_8
      • new_df=pd.concat([left_df,right_df.loc[:,['col_0','col_1','col_8','col_9']],axis=1)
      猜你喜欢
      • 2019-09-17
      • 2021-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-13
      • 2019-12-16
      • 1970-01-01
      相关资源
      最近更新 更多