合并(更新\插入)pandas 数据帧的更好方法

use*_*057 5 python merge dataframe pandas

我有 2 个熊猫数据框 - df_current_data、df_new_data。

我的目标是应用合并(不是 Pandas 合并函数,像“更新\插入”这样的合并)。匹配检查是通过键列进行的。

我的结果需要由 3 个可选的行类型构建。

  1. df_current_data 中存在但 df_new_data 中不存在的行 - 将“按原样”插入结果。

  2. df_new_data 中存在但 df_current_data 中不存在的行 - 将“按原样”插入结果。

  3. 存在于 df_new_data 和 df_current_data 中的行 - 结果需要从 df_new_data 中获取行。

这是一个经典的合并更新插入操作。

例子:

# rows 0,1 are in current and not in new (check by index1 and index2)
# row 2 is common
In [41]: df_current_source
Out[41]:    A  index1  index2
         0  1       1       4
         1  2       2       5
         2  3       3       6

# rows 0,2 are in new and not in current (check by index1 and index2)
# row 1 is common
In [42]: df_new_source
Out[42]:    A  index1  index2
         0  4       2       7
         1  5       3       6
         2  6       4       5

# the result has 2 rows that only in current (rows 0,1)
# the result has 2 rows that only in new (rows 3,4)
# the result has one row that exists in both current and new (row 2 - index1 = 3, index2 = 6) - so the value of the column A is from the new and not from the current (5 instead of 2)

In [43]: df_result
Out[43]:    A  index1  index2
         0  1       1       4
         1  2       2       5
         2  5       3       6
         3  4       2       7
         4  6       4       5
Run Code Online (Sandbox Code Playgroud)

这就是我所做的:

# left join from source to new
df = df_current_source.merge(df_new_source, how='left', left_on=p_new_keys, 
right_on=p_curr_keys, indicator=True)

# take only the rows that exists in the current and not exists in the source
df_only_current = df[df['_merge'] == 'left_only']

# merge new data into current data
df_result = pd.concat([df_only_current, df_new_source])
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用 isin 功能:

df_result = pd.concat([df_current_source[~df_current_source[p_key_col_name]\

.isin(df_new_source[p_key_col_name])], df_new_source])
Run Code Online (Sandbox Code Playgroud)

问题是,如果我有 1 个以上的键列,我不能使用 isin,我需要合并。

假设 current 比 new 大很多,我想最好的方法是直接用 new 的行更新 current 的匹配行,并将“new”数据帧的新行附加到 current 中。

但我不知道该怎么做..

非常感谢。

Sco*_*ton 1

选项 1:用作indicator=True以下部分的一部分merge

df_out = df_current_source.merge(df_new_source, 
                                 on=['index1', 'index2'], 
                                 how='outer', indicator=True)

df_out['A'] = np.where(df_out['_merge'] == 'both',
                       df_out['A_y'],
                       df_out.A_x.add(df_out.A_y, fill_value=0)).astype(int)

df_out[['A', 'index1', 'index2']]
Run Code Online (Sandbox Code Playgroud)

输出:

   A  index1  index2
0  1       1       4
1  2       2       5
2  5       3       6
3  4       2       7
4  6       4       5
Run Code Online (Sandbox Code Playgroud)

选项 2:combined_firstset_index

df_new_source.set_index(['index1', 'index2'])\
             .combine_first(df_current_source.set_index(['index1', 'index2']))\
             .reset_index()\
             .astype(int)
Run Code Online (Sandbox Code Playgroud)

输出:

   index1  index2  A
0       1       4  1
1       2       5  2
2       2       7  4
3       3       6  5
4       4       5  6
Run Code Online (Sandbox Code Playgroud)