pandas DataFrame 中行的高效成对比较

Efficient pairwise comparison of rows in pandas DataFrame

我目前正在处理一个较小的数据集(大约 900 万行)。不幸的是,大多数条目都是字符串,即使对类别进行强制转换,框架在内存中也只有几 GB。

我想做的是将每一行与其他行进行比较,并对内容进行直接比较。例如,给定

   A   B     C      D
0 cat blue  old Saturday
1 dog red   old Saturday

我想计算

      d_A   d_B   d_C   d_D
0, 0  True  True  True  True
0, 1  False False True  True
1, 0  False False True  True
1, 1  True  True  True  True

显然,组合爆炸将排除每个 记录与其他所有记录的比较。所以我们可以改为使用分块,通过应用 groupby,比如在 A 列上。

我的问题是,有没有办法在 pandas 或 dask 中执行此操作,这比以下序列更快:

  1. 按索引分组
  2. 外部将每个组连接到自身以生成对
  3. dataframe.apply 对每一行的比较函数

作为参考,假设我可以访问大量内核(数百个)和大约 200G 内存。

  1. 您可以考虑将您的问题表述为连接操作
  2. 您可以考虑使用分类来减少内存使用

解决方案原来是使用 numpy 代替步骤 3)。虽然我们无法创建每一行的外连接,但我们可以按 A 列中的值分组并创建更小的组以进行外连接。

技巧是使用 numpy.equal.outer(df1, df2).ravel() 当数据帧以这种方式作为输入传递给 numpy 函数时,结果是更快(至少 30 倍)的矢量化结果。例如:

>>> df = pd.DataFrame
   A   B     C      D
0 cat blue  old Saturday
1 dog red   old Saturday

>>> result = pd.DataFrame(columns=["A", "B", "C", "D"], 
                            index=pd.MultiIndex.from_product([df.index, df.index]))
>>> result["A"] = np.equal.outer(df["A"], df["A"]).ravel()
>>> result
        A     B     C     D
0, 0  True   NaN   NaN   NaN  
0, 1  False  NaN   NaN   NaN  
1, 0  False  NaN   NaN   NaN  
1, 1  True   NaN   NaN   NaN  

您可以对每一列重复,或者通过按列应用结果自动执行该过程。