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 中执行此操作,这比以下序列更快:
- 按索引分组
- 外部将每个组连接到自身以生成对
- dataframe.apply 对每一行的比较函数
作为参考,假设我可以访问大量内核(数百个)和大约 200G 内存。
- 您可以考虑将您的问题表述为连接操作
- 您可以考虑使用分类来减少内存使用
解决方案原来是使用 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
您可以对每一列重复,或者通过按列应用结果自动执行该过程。
我目前正在处理一个较小的数据集(大约 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 中执行此操作,这比以下序列更快:
- 按索引分组
- 外部将每个组连接到自身以生成对
- dataframe.apply 对每一行的比较函数
作为参考,假设我可以访问大量内核(数百个)和大约 200G 内存。
- 您可以考虑将您的问题表述为连接操作
- 您可以考虑使用分类来减少内存使用
解决方案原来是使用 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
您可以对每一列重复,或者通过按列应用结果自动执行该过程。