【问题标题】:Efficient pairwise comparison of rows in pandas DataFramepandas DataFrame中行的有效成对比较
【发布时间】:2018-08-13 22:00:49
【问题描述】:

我目前正在处理一个较小的数据集(大约 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 的内存。

【问题讨论】:

  • 您是否需要知道行之间是否完全相等,或者您是否需要知道它们的不同之处(如您提供的输出 DataFrame 中)?
  • 我需要知道它们的不同之处。

标签: python pandas pandas-groupby dask


【解决方案1】:

结果证明解决方案是使用 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  

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

【讨论】:

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

    【讨论】:

    • 仅供参考,我认为第二点已经考虑过了,即even with coercion to categories, the frame sits at a few GB in memory
    猜你喜欢
    • 2023-01-11
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多