【问题标题】:Copy data from df to another df in multiple columns based off one key基于一个键将数据从 df 复制到多列中的另一个 df
【发布时间】:2020-01-20 20:25:48
【问题描述】:

我有两个数据框,df1 和 df2。每个数据帧的唯一标识符是“ID”和“Prop_Number”。我需要将 df1 中的 Num1、2 和 3 列复制到 df2、1_Num 中的相应列中... 但我不确定如何合并超过列。我想将 df2 保留为 df2,而不是创建一个新的 df(因为我的真实数据在 df2 中有更多列)将保持原样。

cols1 = ['ID', 'Num1', 'Num2', 'Num3']
data1 = [['33', '.853', '9834', '234'],
        ['87', '.372', '2345', '843'],
        ['15', '1.234','742', '821'],
        ['92', '1.957', '1234', '123'],
        ['13', '.943', '8427', '493'],
        ['67', '.852', '3421', '439']
       ]
df1 = pd.DataFrame(data=data1, columns=cols1)

cols2 = ['Prop_Number', '1_Num', '2_Num', '3_Num']
data2 = [['87', '', '', ''],
        ['33', '', '', ''],
        ['67', '','', ''],
        ['13', '', '', ''],
        ['92', '', '', ''],
        ['15', '', '', '']
       ]
df2 = pd.DataFrame(data=data2, columns=cols2)

我试过的是

df2['1_Num'] = np.where(df1['ID'] == df2['Prop_Number'], df1['Num1'],np.nan)

【问题讨论】:

  • 两个dfs中的列名是相同还是不同?
  • 列名不同,但您可以关联它们 - df1['Num1'] = df2['1_Num']...

标签: python pandas dataframe merge


【解决方案1】:

你可以试试这个:

cols1 = ['ID', 'Num1', 'Num2', 'Num3']
data1 = [['33', '.853', '9834', '234'],
        ['87', '.372', '2345', '843'],
        ['15', '1.234','742', '821'],
        ['92', '1.957', '1234', '123'],
        ['13', '.943', '8427', '493'],
        ['67', '.852', '3421', '439']
       ]
df1 = pd.DataFrame(data=data1, columns=cols1)

cols2 = ['Prop_Number', '1_Num', '2_Num', '3_Num']
data2 = [['87', '', '', ''],
        ['33', '', '', ''],
        ['67', '','', ''],
        ['13', '', '', ''],
        ['92', '', '', ''],
        ['15', '', '', '']
       ]
df2 = pd.DataFrame(data=data2, columns=cols2)

df2 = df2.set_index('Prop_Number')
df2.update(df1.rename(columns=dict(zip(df1.columns[1:],
                                       ['1_Num','2_Num','3_Num'])))
              .set_index('ID'))
df2 = df2.reset_index()
print(df2)

输出:

  Prop_Number  1_Num 2_Num 3_Num
0          87   .372  2345   843
1          33   .853  9834   234
2          67   .852  3421   439
3          13   .943  8427   493
4          92  1.957  1234   123
5          15  1.234   742   821

详情:renamedf1 列匹配 df2 列并使用set_indexupdate 修改 df2。

【讨论】:

    【解决方案2】:

    Scott 提供了一个很好的答案,但我对您按数字匹配列很感兴趣,并认为这可以帮助您解决问题。

    想法是正则表达式匹配数据框中的所有数字类型列,然后按数字对它们进行排序,这允许我们匹配从 df1 到 df2 的列:

    另外,由于您的索引名称不同,您的索引将返回空白,您可以手动更新它。

    def match_numeric_columns(dataframe1, dataframe2):
    
    """
    the first argument will be the dataframe you want to rename
    takes in two dataframes and returns their alphanumeric 
    values as matches. e.g col1a = 1cola or Data_225 = 225_Info
    """
    
    
       cola = (
            dataframe1.filter(regex="\d").columns)
    
       colb = (
        dataframe2.filter(regex="\d").columns)
    
       all_matches = {
        (k if int(re.findall("\d+", k)[0]) == int(re.findall("\d+", v)[0]) else None): 
        (v if int(re.findall("\d+", v)[0]) == int(re.findall("\d+", k)[0]) else None
        )
        for (k, v) in zip(cola, colb)
       }
    
    
        matching_cols = {k: v for k, v in all_matches.items() if v is not None}
    
        return matching_cols
    

    print(matching_cols(df1,df2))
    {'1_Num': 'Num1', '2_Num': 'Num2', '3_Num': 'Num3'}
    

    df2_v2 = (
        df2.set_index("ID")
        .rename(columns=match_numeric_columns(df2, df1))
        .replace("", np.nan)
        .combine_first(df1.set_index("ID"))
    )
    
    print(df2_v2)
         Num1    Num2   Num3
    13  0.943  8427.0  493.0
    15  1.234   742.0  821.0
    33  0.853  9834.0  234.0
    67  0.852  3421.0  439.0
    87  0.372  2345.0  843.0
    92  1.957  1234.0  123.0
    

    【讨论】:

    • 谢谢,DN。很高兴采取额外的步骤。 +1
    • for 循环又不重置索引呢?
    • @DeAnnaMartinez for loops 不推荐用于 pandas,因为它违背了您使用矢量化解决方案的 API,并且在最后的手段中使用 for 循环。您的意思是不更改索引名称吗?您可以重命名它只需重命名df1 中的索引以匹配df2
    猜你喜欢
    • 1970-01-01
    • 2021-12-25
    • 2022-01-08
    • 2022-12-03
    • 1970-01-01
    • 2016-02-29
    • 2021-10-06
    • 1970-01-01
    • 2020-04-06
    相关资源
    最近更新 更多