pandas 获取不在其他数据框中的行

2024-12-05 08:37:00
admin
原创
86
摘要:问题描述:我有两个熊猫数据框,它们有一些共同的行。假设dataframe2是dataframe1的子集。如何获取 dataframe1 中不在 dataframe2 中的行?df1 = pandas.DataFrame(data = {'col1' : [1, 2, 3, 4, 5], 'col2' : [1...

问题描述:

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

假设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

解决方案 1:

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)

解决方案 2:

一种方法是存储两个 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

编辑

您发现的另一种方法是使用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

解决方案 3:

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

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

解决方案 4:

正如已经暗示的那样,isin 要求列和索引相同才能匹配。如果匹配只针对行内容,则获取用于筛选现有行的掩码的一种方法是将行转换为(多)索引:

In [77]: df1 = pandas.DataFrame(data = {'col1' : [1, 2, 3, 4, 5, 3], 'col2' : [10, 11, 12, 13, 14, 10]})
In [78]: df2 = pandas.DataFrame(data = {'col1' : [1, 3, 4], 'col2' : [10, 12, 13]})
In [79]: df1.loc[~df1.set_index(list(df1.columns)).index.isin(df2.set_index(list(df2.columns)).index)]
Out[79]:
   col1  col2
1     2    11
4     5    14
5     3    10

如果要考虑索引,set_index 有关键字参数 append,用于将列附加到现有索引。如果列不对齐,可以用列规范替换 list(df.columns) 来对齐数据。

pandas.MultiIndex.from_tuples(df<N>.to_records(index = False).tolist())

也可以用于创建索引,但我怀疑这是否更有效。

解决方案 5:

假设您有两个数据框,df_1 和 df_2 具有多个字段(column_names),并且您想要根据某些字段(例如 fields_x、fields_y)找到 df_1 中不在 df_2 中的条目,请按照以下步骤操作。

步骤1.向df_1和df_2分别添加列key1和key2。

步骤2.合并数据框,如下所示。field_x 和 field_y 是我们想要的列。

步骤3.从 df_1 中仅选择 key1 不等于 key2 的行。

步骤4.放下key1和key2。

此方法将解决您的问题,即使处理大数据集也能快速运行。我已经尝试过将其用于包含超过 1,000,000 行的数据框。

df_1['key1'] = 1
df_2['key2'] = 1
df_1 = pd.merge(df_1, df_2, on=['field_x', 'field_y'], how = 'left')
df_1 = df_1[~(df_1.key2 == df_1.key1)]
df_1 = df_1.drop(['key1','key2'], axis=1)

解决方案 6:

这是最好的方法:

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']

请注意,删除重复项用于最小化比较。没有它们也可以工作。最好的方法是比较行内容本身,而不是索引或一列/两列,相同的代码也可以用于其他过滤器,如“both”和“right_only”,以获得类似的结果。对于此语法,数据框可以有任意数量的列,甚至不同的索引。只有列应该出现在两个数据框中。

为什么这是最好的方法?

  1. index.difference 仅适用于基于唯一索引的比较

  2. pandas.concat()加上drop_duplicated()并不理想,因为它还会摆脱可能仅存在于您想要保留的数据框中并且由于有效原因而重复的行。

解决方案 7:

我认为那些包含合并的答案非常慢。因此,我建议使用另一种方法来获取两个数据框之间不同的行:

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

免责声明:如果您对两个数据框不同的特定列感兴趣,我的解决方案有效。如果您只对所有列都相同的行感兴趣,请不要使用此方法。

假设 col1 是一种 ID,并且您只想获取不包含在两个数据框中的那些行:

ids_in_df2 = df2.col1.unique()
not_found_ids = df[~df['col1'].isin(ids_in_df2 )]

就是这样。您将获得一个数据框,其中仅包含 col1 未出现在两个数据框中的行。

解决方案 8:

有点晚了,但可能值得检查 pd.merge 的“指标”参数。

请参阅另一个问题以获取示例:
比较 PandaS DataFrames 并返回第一个缺少的行

解决方案 9:

我有一个更简单的方法,只需两个简单的步骤:正如OP提到的,假设dataframe2是dataframe1的子集,两个数据框中的列相同,

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

### Step 1: just append the 2nd df at the end of the 1st df 
df_both = df1.append(df2)

### Step 2: drop rows which contain duplicates, Drop all duplicates.
df_dif = df_both.drop_duplicates(keep=False)

## mission accompliched!
df_dif
Out[20]: 
   col1  col2
3     4    13
4     5    14
5     3    10

解决方案 10:

您还可以连接df1, df2

x = pd.concat([df1, df2])

然后删除所有重复项:

y = x.drop_duplicates(keep=False, inplace=False)

解决方案 11:

使用合并函数提取不同的行

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

将不同的行保存在 CSV 中

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

解决方案 12:

您可以使用isin(dict)方法来完成:

In [74]: df1[~df1.isin(df2.to_dict('l')).all(1)]
Out[74]:
   col1  col2
3     4    13
4     5    14

解释:

In [75]: df2.to_dict('l')
Out[75]: {'col1': [1, 2, 3], 'col2': [10, 11, 12]}

In [76]: df1.isin(df2.to_dict('l'))
Out[76]:
    col1   col2
0   True   True
1   True   True
2   True   True
3  False  False
4  False  False

In [77]: df1.isin(df2.to_dict('l')).all(1)
Out[77]:
0     True
1     True
2     True
3    False
4    False
dtype: bool

解决方案 13:

这是解决这个问题的另一种方法:

df1[~df1.index.isin(df1.merge(df2, how='inner', on=['col1', 'col2']).index)]

或者:

df1.loc[df1.index.difference(df1.merge(df2, how='inner', on=['col1', 'col2']).index)]

解决方案 14:

更轻松、更简单、更优雅

uncommon_indices = np.setdiff1d(df1.index.values, df2.index.values)
new_df = df1.loc[uncommon_indices,:]

解决方案 15:

我这样做的方法是添加一个特定于一个数据框的新列,并使用它来选择是否保留条目

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;如果该条目在两个 dataFrames 中都存在,则为 1。然后,您可以使用它来限制您想要的内容

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

解决方案 16:

这个怎么样:

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]})
records_df2 = set([tuple(row) for row in df2.values])
in_df2_mask = np.array([tuple(row) in records_df2 for row in df1.values])
result = df1[~in_df2_mask]

解决方案 17:

为两个 DataFrames 定义一个索引,然后使用.drop()

df
# 1100 rows

xx
# 1000 rows

df.drop(xx.index)
# 100 rows

相反的是df.take(xx.index)

解决方案 18:

pd.concat([df1, df2]).drop_duplicates(keep=False)将把两个 DataFrame 连接在一起,然后删除所有重复项,只保留唯一行。默认情况下,它将保留重复项的第一次出现,但设置keep=False将删除所有重复项。

请记住,如果您需要比较具有不同名称的列的 DataFrames,则必须确保在连接数据框之前列具有相同的名称。

此外,如果数据框的列顺序不同,也会影响最终结果。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   984  
  在项目管理领域,CDCP(Certified Data Center Professional)认证评审是一个至关重要的环节,它不仅验证了项目团队的专业能力,还直接关系到项目的成功与否。在这一评审过程中,沟通技巧的运用至关重要。有效的沟通不仅能够确保信息的准确传递,还能增强团队协作,提升评审效率。本文将深入探讨CDCP...
华为IPD流程   0  
  IPD(Integrated Product Development,集成产品开发)是一种以客户需求为核心、跨部门协同的产品开发模式,旨在通过高效的资源整合和流程优化,提升产品开发的成功率和市场竞争力。在IPD培训课程中,掌握关键成功因素是确保团队能够有效实施这一模式的核心。以下将从五个关键成功因素展开讨论,帮助企业和...
IPD项目流程图   0  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司在其全球化进程中逐步构建和完善的一套高效产品开发管理体系。这一流程不仅帮助华为在技术创新和产品交付上实现了质的飞跃,还为其在全球市场中赢得了显著的竞争优势。IPD的核心在于通过跨部门协作、阶段性评审和市场需求驱动,确保...
华为IPD   0  
  华为作为全球领先的通信技术解决方案提供商,其成功的背后离不开一套成熟的管理体系——集成产品开发(IPD)。IPD不仅是一种产品开发流程,更是一种系统化的管理思想,它通过跨职能团队的协作、阶段评审机制和市场需求驱动的开发模式,帮助华为在全球市场中脱颖而出。从最初的国内市场到如今的全球化布局,华为的IPD体系在多个领域展现...
IPD管理流程   0  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用