我正在尝试覆盖两个数据帧,如果几列中的值匹配,则用另一个数据帧的值覆盖一个数据帧。我不关心数据帧的索引,重要的是列中的内容与覆盖发生匹配。当发生此匹配时,从一个数据帧中删除行并仅连接其余行也是可以接受的。
下面是两个模拟数据帧,为简洁起见,它们具有简化的列名称。第一个是"背景"数据帧,我希望在其上叠加另一个内容,
Name1 Name2 Id1 Id2 Attr1 Attr2
3 A B 0 0 None None
1 A B 0 1 None None
7 A B 0 2 None None
15 A B 0 3 None None
13 A B 1 0 None None
14 A B 1 1 None None
0 A B 1 2 None None
4 A B 1 3 None None
10 A B 2 0 None None
9 A B 2 1 None None
12 A B 2 2 None None
11 A B 2 3 None None
6 A B 3 0 None None
8 A B 3 1 None None
2 A B 3 2 None None
5 A B 3 3 None None
第二个包含一些数据
Name1 Name2 Id1 Id2 Attr1 Attr2
0 A B 0 0 LEVEL_A 1.00
1 A B 0 1 LEVEL_A 0.97
2 A B 1 1 LEVEL_A 1.00
3 A B 2 2 LEVEL_A 1.00
4 A B 3 3 LEVEL_A 1.00
我包括索引以表明它们不匹配。预期结果将包含以下数据:
Name1 Name2 Id1 Id2 Attr1 Attr2
3 A B 0 0 Level_A 1.00 # Name1,Name2,Id1,Id2 matches
1 A B 0 1 Level_A 0.97
7 A B 0 2 None None
15 A B 0 3 None None
13 A B 1 0 None None
14 A B 1 1 Level_A 1.00
0 A B 1 2 None None
4 A B 1 3 None None
10 A B 2 0 None None
9 A B 2 1 None None
12 A B 2 2 Level_A 1.00
11 A B 2 3 None None
6 A B 3 0 None None
8 A B 3 1 None None
2 A B 3 2 None None
5 A B 3 3 Level_A 1.00
注意:如果行在最终结果中的顺序不同,那很好。如果找到第一个数据帧中的所有行,以便对于任何给定行,其列Name1,Name2,Id1,Id2
的值也存在于第二个数据帧中,则会出现这种情况。
奖励:我很想知道如果不使用哨兵值(如None
(,是否可以做到这一点,如果可能的话,如何做到这一点?
我一直弄错了,因为combine_first
、isin
等人都看指数。我非常危险地接近使用一些iterrow
方法执行此操作,但这感觉很hack,我不想对我的单元测试进行单元测试。大流行的大脑让我思考得不那么好。
check_cols = 'Name1 Name2 Id1 Id2'.split()
val_cols = 'Attr1 Attr2'.split()
创建唯一 ID
background_df['full_id'] = background_df[check_cols].apply(lambda row: '_'.join([str(_).strip() for _ in row]), axis=1)
data_df['full_id'] = data_df[check_cols].apply(lambda row: '_'.join([str(_).strip() for _ in row]), axis=1)
合并唯一 ID。 您可以更改后缀以帮助您稍后删除多余的列
background_df.merge(data_df, how='left', on='full_id', suffixes=('_x', '_y'))
然后,您将删除不想要的任何列,或者只是以较少的列开始合并。
background_df[check_cols+['full_id',]].merge(data_df[val_cols+['full_id',]], how='left', on='full_id', suffixes=('_x', '_y'))
还有你不谈论的额外事情。您是否有关于 cols Attr1 和 Attr background_df 2 的信息,您希望保留这些信息,而不是data_df中可能的内容? 如果是这样,那么这需要进一步检查_x和_y属性列。
我喜欢使用迭代行,但你特别说不。