合并两个数据帧,同时考虑其中一个数据帧中的新行

merge two dataframes taking into account new rows in one of them

具有以下数据帧,

df1

   Device  name  Rev serial
0      D1  fpc0    1    xyz
1      D1  pic0    1    xxx
2      D2  fpc0    1    hij
3      D2  pic0    1   hijj
4      D3  fpc0    2    xyx
5      D3  pic0    1    xll
6      D3  fpc1    2    xhh
7      D4  fpc1    1    tll
8      D4  fpc2    1    xho
9      D4  pic0    1    lss
10     D5  fpc0    1    qqq
11     D5  pic0    1    xqz

df2

   Device  name  Rev serial
0      D1  fpc0    1    xyz
1      D1  pic0    1    xxx
2      D2  fpc0    1    hij
3      D2  pic0    1   xxxx
4      D3  fpc0    2    xij
5      D3  pic0    1    xll
6      D3  fpc1    2    xhh
7      D3  pic1    1    xtt
8      D4  fpc1    1    tll
9      D4  fpc2    1    xho
10     D4  pic0    1    lss
11     D4  pic1    2    xss
12     D5  fpc0    1    qqq
13     D5  pic0    1    xqz
14     D5  pic1    2    xpr

,其中设备可以在两个数据帧或不同数据帧中具有相同的行数,我不知道是否可以通过简单的方式实现以下(即具有单个索引):

预期输出:

   Device  name  Rev serial      _merge   new_values
0      D1  fpc0    1    xyz        both   False
1      D1  pic0    1    xxx        both   False
2      D2  fpc0    1    hij        both   False
3      D2  pic0    1   hijj   left_only   False
4      D3  fpc0    2    xyx   left_only   False
5      D3  pic0    1    xll   left_only   False
6      D3  fpc1    2    xhh        both   False
7      D4  fpc1    1    tll        both   False
8      D4  fpc2    1    xho        both   False
9      D4  pic0    1    lss        both   False
10     D5  fpc0    1    qqq        both   False
11     D5  pic0    1    xqz        both   False
12     D2  pic0    1   xxxx  right_only   False
13     D3  fpc0    2    xij  right_only   False
14     D3  pic1    1    xll  right_only   False
15     D3  pic0    1    xtt  right_only   True
16     D4  pic1    2    xss  right_only   True
17     D5  pic1    2    xpr  right_only   True

new_values 列表示 df2 中的此设备具有“新”条目:

例如:

在 df1 中我们有:

4      D3  fpc0    2    xyx
5      D3  pic0    1    xll
6      D3  fpc1    2    xhh

在 df2 中我们有:

4      D3  fpc0    2    xij
5      D3  pic0    1    xll
6      D3  fpc1    2    xhh
7      D3  pic0    1    xtt <--- this row is new for this device

基本上我们可以有2种情况:

案例一

一个设备(D1、D2 等...)在两个数据帧中可以具有相同的行数(元素可以相同或不同):

D1 和 D2(在这种情况下所有行都相等)

df1

0      D1  fpc0    1    xyz   
1      D1  pic0    1    xxx   
2      D2  fpc0    1    hij   
3      D2  pic0    1   xxxx   

df2

0      D1  fpc0    1    xyz  
1      D1  pic0    1    xxx  
2      D2  fpc0    1    hij  
3      D2  pic0    1   xxxx  

案例二

一个设备可以在一个数据帧中有 X 行,在另一个数据帧中有 X+y(元素可以相同或不同):

df1


5      D3  pic0    1    xll
6      D3  fpc1    2    xhh
7      D4  fpc1    1    tll
8      D4  fpc2    1    xho
9      D4  pic0    1    lss
10     D5  fpc0    1    qqq
11     D5  pic0    1    xqz

df2

4      D3  fpc0   2    xij
5      D3  pic1    1    xll
6      D3  fpc1    2    xhh
7      D3  pic0    1    xtt
8      D4  fpc1    1    tll
9      D4  fpc1    1    xho
10     D4  pic0    1    lss
11     D4  pic1    2    xss
12     D5  fpc0    1    qqq
13     D5  pic0    1    xqz
14     D5  pic1    2    xpr

在这种情况下,df2 中的索引 6 和 7 是 D3 的“新”,索引 11 是 D4 的“新”,索引 14 是 D5 的“新”。

我在这里做了一个非常相似的问题:

但是我没有考虑到一些事情。

谢谢。

我试过下面的方法,但我不确定它是否最优

df1['_common_1'] = df1['Device'] + df1['name']
df1['_common_2'] = df1['Device'] + df2['name']

final_df = pd.merge(df1,df2,how='outer',indicator=True)

final_df['new_values'] = ~final_df.pop('_common_2').isin(final_df.pop('_common_1'))

   Device  name  Rev serial      _merge  new_values
0      D1  fpc0    1    xyz        both       False
1      D1  pic0    1    xxx        both       False
2      D2  fpc0    1    hij        both       False
3      D2  pic0    1   hijj   left_only       False
4      D3  fpc0    2    xyx   left_only       False
5      D3  pic0    1    xll        both       False
6      D3  fpc1    2    xhh        both       False
7      D4  fpc1    1    tll        both       False
8      D4  fpc2    1    xho        both       False
9      D4  pic0    1    lss        both       False
10     D5  fpc0    1    qqq        both       False
11     D5  pic0    1    xqz        both       False
12     D2  pic0    1   xxxx  right_only       False
13     D3  fpc0    2    xij  right_only       False
14     D3  pic1    1    xtt  right_only        True
15     D4  pic1    2    xss  right_only        True
16     D5  pic1    2    xpr  right_only        True