我有两个熊猫数据帧,它们有一些相同的行。

假设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]})

df1

   col1  col2
0     1    10
1     2    11
2     3    12
3     4    13
4     5    14

df2

   col1  col2
0     1    10
1     2    11
2     3    12

预期结果:

   col1  col2
3     4    13
4     5    14

当前回答

一种方法是在两个dfs中存储一个内部合并表单的结果,然后我们可以简单地选择当一列的值不在这个公共值时的行:

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

EDIT

你已经发现的另一个方法是使用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

其他回答

使用merge函数提取不同的行

df = df1.merge(df2.drop_duplicates(), on=['col1','col2'], 
               how='left', indicator=True)

在CSV中保存不同的行

df[df['_merge'] == 'left_only'].to_csv('output.csv')

我这样做的方法包括添加一个新的列,该列对一个数据框架是唯一的,并使用它来选择是否保留一个条目

df2[col3] = 1
df1 = pd.merge(df_1, df_2, on=['field_x', 'field_y'], how = 'outer')
df1['Empt'].fillna(0, inplace=True)

这使得df1中的每个条目都有一个代码-如果它对df1是唯一的,则为0,如果它在两个数据框架中都是1。然后使用它来限制您想要的内容

answer = nonuni[nonuni['Empt'] == 0]

一种方法是在两个dfs中存储一个内部合并表单的结果,然后我们可以简单地选择当一列的值不在这个公共值时的行:

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

EDIT

你已经发现的另一个方法是使用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

这是最好的方法:

df = df1.drop_duplicates().merge(df2.drop_duplicates(), on=df2.columns.to_list(), 
                   how='left', indicator=True)
df.loc[df._merge=='left_only',df.columns!='_merge']

注意,drop duplicate用于最小化比较。没有他们也可以。最好的方法是比较行内容本身,而不是索引或一/两列,同样的代码也可以用于其他过滤器,如'both'和'right_only',以达到类似的结果。对于这种语法,数据帧可以有任意数量的列,甚至可以有不同的索引。只有列应该出现在两个数据框架中。

为什么这是最好的方法?

索引。差异只适用于基于唯一索引的比较 Pandas.concat()与drop_duplication()结合使用并不理想,因为它还会删除可能只存在于你想保留的数据帧中的行,并出于合理的原因进行复制。

假设索引在数据帧中是一致的(不考虑实际的col值):

df1[~df1.index.isin(df2.index)]