如何使用pandas高效地查找两个大数据框之间的逆交集?

5

我试图找到两个大型数据框之间的反向交集。 我使用下面的代码片段让它运行起来。不幸的是,这种方法在大型数据框上速度太慢,如下所述。你能想到一种更快的方法来计算这个结果吗?

import pandas as pd

df_1 = pd.DataFrame({'a': [8, 2, 2],
                     'b': [0, 1, 3],
                     'c': [0, 2, 2],
                     'd': [0, 2, 2],
                     'e': [0, 2, 2]})

df_2 = pd.DataFrame({'a': [8, 2, 2, 2, 8, 2],
                     'b': [0, 1, 1, 6, 0, 1],
                     'c': [0, 3, 2, 2, 0, 2],
                     'd': [0, 4, 2, 2, 0, 4],
                     'e': [0, 1, 2, 2, 0, 2]})

l_columns = ['a','b','e']

def df_drop_df(df_1, df_2, l_columns):
    """
    Eliminates all equal rows present in dataframe 1 (df_1) from dataframe 2 (df_2) depending on a subset of columns (l_columns)

    :param df_1: dataframe that defines which rows to be removed
    :param df_2: dataframe that is reduced
    :param l_columns: list of column names, present in df_1 and df_2, that is used for the comparison

    :return df_out: final dataframe
    """
    df_1r = df_1[l_columns]
    df_2r = df_2[l_columns].reset_index()

    df_m = pd.merge(df_1r, df_2r, on=l_columns, how='inner')
    row_indexes_m = df_m['index'].to_list()

    row_indexes_df_2 = df_2.index.to_list()
    row_indexes_out = [x for x in row_indexes_df_2 if x not in row_indexes_m]

    df_out = df_2.loc[row_indexes_out]
    return df_out

给出以下正确结果:
#row_indexes_out = [1,3]

df_output = df_drop_df(df_1, df_2, l_columns)
df_output

({'a': [2, 2],
  'b': [1, 6],
  'c': [3, 2],
  'd': [4, 2],
  'e': [1, 2]})

然而,在实际应用中,数据框的大小具有以下尺寸,需要在我的本地计算机上花费大约30分钟:

变量 形状
df1 (3300,77)
df2 (642000,77)
l_columns 列表 12
df_out (611000,77)

(这意味着每个出现在 df_1 中的行在 df_2 中出现了大约 10 次)

您能想到更快计算此结果的方法吗?


您是否正在寻找关于两个数据帧的交集在共同列方面的补集? - Serge de Gosson de Varennes
是的,交集的补集比我称之为“反向交集”更正确。花费时间较长的应该是合并步骤,而不是问题的反演,对吗?这不仅仅是所有共同列,而是特定的列(两个数据框都需要共同拥有)。 - ICurtis
2
你能确定你得到的是否真正是使用作为键的列给定交集的补集吗?我得到了额外的一行,但我只使用了补集的定义。 - Serge de Gosson de Varennes
你能发一下你正在做什么吗?结果应该是第一行和第三行,因为这两个数据框在列a、b和e上进行比较。 - ICurtis
1个回答

4
你可以尝试替换以下行:
row_indexes_df_2 = df_2.index.to_list()
row_indexes_out = [x for x in row_indexes_df_2 if x not in row_indexes_m]

df_out = df_2.loc[row_indexes_out]

使用波浪线运算符:

df_out = df_2.loc[~df_2.index.isin(row_indexes_m)]

这将显著减少时间。


这一步现在在我的本地机器上只需要0.5秒来处理大型数据框。 - ICurtis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接