我有两个共有数据行的熊猫数据框。
假设dataframe2是dataframe1的子集。
如何获取dataframe1中不在dataframe2中的行?
df1 = pandas.DataFrame(data = {'col1' : [1, 2, 3, 4, 5], 'col2' : [10, 11, 12, 13, 14]}) df2 = pandas.DataFrame(data = {'col1' : [1, 2, 3], 'col2' : [10, 11, 12]})
一种方法是存储两个df的内部合并结果,然后我们可以简单地选择当一列的值不在此通用值中时的行:
In [119]: common = df1.merge(df2,on=['col1','col2']) print(common) df1[(~df1.col1.isin(common.col1))&(~df1.col2.isin(common.col2))] col1 col2 0 1 10 1 2 11 2 3 12 Out[119]: col1 col2 3 4 13 4 5 14
编辑
您发现的另一种方法是使用isin它将产生NaN可删除的行:
In [138]: df1[~df1.isin(df2)].dropna() Out[138]: col1 col2 3 4 13 4 5 14
但是,如果df2不能以相同的方式开始行,那么它将行不通:
df2 = pd.DataFrame(data = {'col1' : [2, 3,4], 'col2' : [11, 12,13]})
将产生整个df:
In [140]: df1[~df1.isin(df2)].dropna() Out[140]: col1 col2 0 1 10 1 2 11 2 3 12 3 4 13 4 5 14
当前选择的解决方案产生不正确的结果。为了正确解决此问题,我们可以执行从df1到的左联接df2,确保首先仅获得的唯一行df2。
首先,我们需要修改原始DataFrame以添加包含数据的行[3,10]。
df1 = pd.DataFrame(data = {'col1' : [1, 2, 3, 4, 5, 3], 'col2' : [10, 11, 12, 13, 14, 10]}) df2 = pd.DataFrame(data = {'col1' : [1, 2, 3], 'col2' : [10, 11, 12]}) df1 col1 col2 0 1 10 1 2 11 2 3 12 3 4 13 4 5 14 5 3 10 df2 col1 col2 0 1 10 1 2 11 2 3 12
执行左联接,消除中的重复项,df2以便df1联接的每一行都恰好有1行df2。使用该参数indicator返回一个额外的列,指示该行来自哪个表。
df_all = df1.merge(df2.drop_duplicates(), on=['col1','col2'], how='left', indicator=True) df_all col1 col2 _merge 0 1 10 both 1 2 11 both 2 3 12 both 3 4 13 left_only 4 5 14 left_only 5 3 10 left_only 创建一个布尔条件: df_all['_merge'] == 'left_only' 0 False 1 False 2 False 3 True 4 True 5 True Name: _merge, dtype: bool
为什么其他解决方案是错误的 一些解决方案会犯同样的错误-他们仅检查每个值在每一列中是否独立,而不是在同一行中。添加最后一行,这是唯一的,但具有两列中的值,则会显示df2以下错误:
common = df1.merge(df2,on=['col1','col2']) (~df1.col1.isin(common.col1))&(~df1.col2.isin(common.col2)) 0 False 1 False 2 False 3 True 4 True 5 False dtype: bool
此解决方案得到相同的错误结果:
df1.isin(df2.to_dict('l')).all(1)