如何在数据框中提取另一个中不存在的行

时间:2017-02-12 15:47:26

标签: python pandas dataframe

我有两个数据帧:

all_data:

              AID       VID  Freq
0        00016A3E  0127C661     1
1        00016A3E  0C05DA5D     2
2        00016A3E  0C032814     1
3        00016A3E  0BF6C78D     1
4        00016A3E  0A79DFF1     1
5        00016A3E  07BD2FB2     1
6        00016A3E  0790E61B     1
7        00016A3E  0C24ED25     3
8        00016A3E  073630B5     3
9        00016A3E  06613535     1
10       00016A3E  05F809AF     1
11       00016A3E  05C625FF     1
12       00016A3E  04220EA8     4
13       00016A3E  013A29E5     1
14       00016A3E  0761C98A     1
15       00016AE9  0A769475    16
16       00016AE9  0A7DED0A     2
17       00016AE9  0ABF60DF     9
18       00016AE9  0AE3F25A     2
19       00016AE9  0AEFE12F     5
20       00016AE9  0BD8975A     2
21       00016AE9  44DF880B     1
22       00016AE9  43F9E08E     2
23       00016AE9  44EA5E08     2
24       00016AE9  4539ED1E    16
25       00016AE9  8516B55A     4
26       00016AE9  0972AFF2     1
27       00016AE9  0C559B34     1
28       00016AE9  06B5C040     7
29       00016AE9  0B0426FA     1

子集:

             AID       VID  Freq
0       00016A3E  0C24ED25     3
1       00016A3E  0C05DA5D     2
2       00016AE9  0B0426FA     1
3       00016AE9  0AEFE12F     5

我需要创建第三个数据框,其中all_data中的所有行都不存在于subset中。请注意,subset中的所有行都存在于all_data中。

所以这个实例中的新df应该是:

              AID       VID  Freq
0        00016A3E  0127C661     1
2        00016A3E  0C032814     1
3        00016A3E  0BF6C78D     1
4        00016A3E  0A79DFF1     1
5        00016A3E  07BD2FB2     1
6        00016A3E  0790E61B     1
8        00016A3E  073630B5     3
9        00016A3E  06613535     1
10       00016A3E  05F809AF     1
11       00016A3E  05C625FF     1
12       00016A3E  04220EA8     4
13       00016A3E  013A29E5     1
14       00016A3E  0761C98A     1
15       00016AE9  0A769475    16
16       00016AE9  0A7DED0A     2
17       00016AE9  0ABF60DF     9
18       00016AE9  0AE3F25A     2
20       00016AE9  0BD8975A     2
21       00016AE9  44DF880B     1
22       00016AE9  43F9E08E     2
23       00016AE9  44EA5E08     2
24       00016AE9  4539ED1E    16
25       00016AE9  8516B55A     4
26       00016AE9  0972AFF2     1
27       00016AE9  0C559B34     1
28       00016AE9  06B5C040     7

我尝试了此处描述的方法:pandas get rows which are NOT in other dataframe但它们不起作用,因为每个数据框中的索引都不匹配。

3 个答案:

答案 0 :(得分:1)

您可以将merge(..., how='left', indicator=True)query()方法结合使用:

In [38]: pd.merge(all_data, subset, how='left', indicator=True) \
           .query("_merge == 'left_only'") \
           .drop('_merge',1)
Out[38]:
         AID       VID  Freq
0   00016A3E  0127C661     1
2   00016A3E  0C032814     1
3   00016A3E  0BF6C78D     1
4   00016A3E  0A79DFF1     1
5   00016A3E  07BD2FB2     1
6   00016A3E  0790E61B     1
8   00016A3E  073630B5     3
9   00016A3E  06613535     1
10  00016A3E  05F809AF     1
11  00016A3E  05C625FF     1
12  00016A3E  04220EA8     4
13  00016A3E  013A29E5     1
14  00016A3E  0761C98A     1
15  00016AE9  0A769475    16
16  00016AE9  0A7DED0A     2
17  00016AE9  0ABF60DF     9
18  00016AE9  0AE3F25A     2
20  00016AE9  0BD8975A     2
21  00016AE9  44DF880B     1
22  00016AE9  43F9E08E     2
23  00016AE9  44EA5E08     2
24  00016AE9  4539ED1E    16
25  00016AE9  8516B55A     4
26  00016AE9  0972AFF2     1
27  00016AE9  0C559B34     1
28  00016AE9  06B5C040     7

一步一步:

In [39]: pd.merge(all_data, subset, how='left', indicator=True)
Out[39]:
         AID       VID  Freq     _merge
0   00016A3E  0127C661     1  left_only
1   00016A3E  0C05DA5D     2       both
2   00016A3E  0C032814     1  left_only
3   00016A3E  0BF6C78D     1  left_only
4   00016A3E  0A79DFF1     1  left_only
5   00016A3E  07BD2FB2     1  left_only
6   00016A3E  0790E61B     1  left_only
7   00016A3E  0C24ED25     3       both
8   00016A3E  073630B5     3  left_only
9   00016A3E  06613535     1  left_only
10  00016A3E  05F809AF     1  left_only
11  00016A3E  05C625FF     1  left_only
12  00016A3E  04220EA8     4  left_only
13  00016A3E  013A29E5     1  left_only
14  00016A3E  0761C98A     1  left_only
15  00016AE9  0A769475    16  left_only
16  00016AE9  0A7DED0A     2  left_only
17  00016AE9  0ABF60DF     9  left_only
18  00016AE9  0AE3F25A     2  left_only
19  00016AE9  0AEFE12F     5       both
20  00016AE9  0BD8975A     2  left_only
21  00016AE9  44DF880B     1  left_only
22  00016AE9  43F9E08E     2  left_only
23  00016AE9  44EA5E08     2  left_only
24  00016AE9  4539ED1E    16  left_only
25  00016AE9  8516B55A     4  left_only
26  00016AE9  0972AFF2     1  left_only
27  00016AE9  0C559B34     1  left_only
28  00016AE9  06B5C040     7  left_only
29  00016AE9  0B0426FA     1       both

In [40]: pd.merge(all_data, subset, how='left', indicator=True).query("_merge == 'left_only'")
Out[40]:
         AID       VID  Freq     _merge
0   00016A3E  0127C661     1  left_only
2   00016A3E  0C032814     1  left_only
3   00016A3E  0BF6C78D     1  left_only
4   00016A3E  0A79DFF1     1  left_only
5   00016A3E  07BD2FB2     1  left_only
6   00016A3E  0790E61B     1  left_only
8   00016A3E  073630B5     3  left_only
9   00016A3E  06613535     1  left_only
10  00016A3E  05F809AF     1  left_only
11  00016A3E  05C625FF     1  left_only
12  00016A3E  04220EA8     4  left_only
13  00016A3E  013A29E5     1  left_only
14  00016A3E  0761C98A     1  left_only
15  00016AE9  0A769475    16  left_only
16  00016AE9  0A7DED0A     2  left_only
17  00016AE9  0ABF60DF     9  left_only
18  00016AE9  0AE3F25A     2  left_only
20  00016AE9  0BD8975A     2  left_only
21  00016AE9  44DF880B     1  left_only
22  00016AE9  43F9E08E     2  left_only
23  00016AE9  44EA5E08     2  left_only
24  00016AE9  4539ED1E    16  left_only
25  00016AE9  8516B55A     4  left_only
26  00016AE9  0972AFF2     1  left_only
27  00016AE9  0C559B34     1  left_only
28  00016AE9  06B5C040     7  left_only

答案 1 :(得分:1)

这对我有用:

merged = all_data.merge(subset, how='left', indicator=True)
print(merged[merged['_merge']=='left_only'])

合并后,您可以按_merge left_only值进行过滤。

答案 2 :(得分:1)

如果您在all_data中没有重复项,则这里有一种没有合并但有drop_duplicates的方法。 keep=False参数删除所有重复行:

pd.concat([all_data, subset]).drop_duplicates(keep=False)
Out[23]: 
         AID       VID  Freq
0   00016A3E  0127C661     1
2   00016A3E  0C032814     1
3   00016A3E  0BF6C78D     1
4   00016A3E  0A79DFF1     1
5   00016A3E  07BD2FB2     1
6   00016A3E  0790E61B     1
8   00016A3E  073630B5     3
9   00016A3E  06613535     1
10  00016A3E  05F809AF     1
11  00016A3E  05C625FF     1
12  00016A3E  04220EA8     4
13  00016A3E  013A29E5     1
14  00016A3E  0761C98A     1
15  00016AE9  0A769475    16
16  00016AE9  0A7DED0A     2
17  00016AE9  0ABF60DF     9
18  00016AE9  0AE3F25A     2
20  00016AE9  0BD8975A     2
21  00016AE9  44DF880B     1
22  00016AE9  43F9E08E     2
23  00016AE9  44EA5E08     2
24  00016AE9  4539ED1E    16
25  00016AE9  8516B55A     4
26  00016AE9  0972AFF2     1
27  00016AE9  0C559B34     1
28  00016AE9  06B5C040     7

%timeit pd.concat([all_data, subset]).drop_duplicates(keep=False)
1000 loops, best of 3: 1.53 ms per loop

%%timeit
pd.merge(all_data, subset, how='left', indicator=True) \
           .query("_merge == 'left_only'") \
           .drop('_merge',1)
100 loops, best of 3: 8.58 ms per loop