这篇文章的内容原本是 Pandas Merging 101 的一部分,但由于完全公正地处理这个主题所需的内容的性质和大小,它已被移到它自己的 QnA 中。
给定两个简单的 DataFrame;
left = pd.DataFrame({'col1' : ['A', 'B', 'C'], 'col2' : [1, 2, 3]})
right = pd.DataFrame({'col1' : ['X', 'Y', 'Z'], 'col2' : [20, 30, 50]})
left
col1 col2
0 A 1
1 B 2
2 C 3
right
col1 col2
0 X 20
1 Y 30
2 Z 50
可以计算这些帧的叉积,类似于:
A 1 X 20
A 1 Y 30
A 1 Z 50
B 2 X 20
B 2 Y 30
B 2 Z 50
C 3 X 20
C 3 Y 30
C 3 Z 50
计算此结果的最有效方法是什么?
原文由 cs95 发布,翻译遵循 CC BY-SA 4.0 许可协议
让我们从建立一个基准开始。解决此问题的最简单方法是使用临时“键”列:
熊猫 <= 1.1.X
熊猫 >= 1.2
这是如何工作的,两个 DataFrame 都被分配了一个具有相同值(比如 1)的临时“键”列。
merge
然后对“键”执行多对多连接。虽然多对多 JOIN 技巧适用于大小合理的 DataFrame,但您会发现在处理较大数据时性能相对较低。
更快的实现将需要 NumPy。下面是一些著名 的一维笛卡尔积的 NumPy 实现。我们可以在其中一些高性能解决方案的基础上构建以获得我们想要的输出。然而,我最喜欢的是@senderle 的第一个实现。
泛化:在唯一 或非 唯一索引数据帧上交叉连接
这个技巧适用于任何类型的 DataFrame。我们使用前面提到的
cartesian_product
计算数据帧的数字索引的笛卡尔积,用它来重新索引数据帧,并且并且,沿着类似的路线,
该解决方案可以推广到多个 DataFrame。例如,
进一步简化
当 只处理两个 DataFrame 时,不涉及 @senderle 的
cartesian_product
的更简单的解决方案是可能的。使用np.broadcast_arrays
,我们可以获得几乎相同的性能水平。性能比较
在一些具有唯一索引的人为设计的 DataFrame 上对这些解决方案进行基准测试,我们有
请注意,时间可能会根据您的设置、数据和对
cartesian_product
辅助函数的选择而有所不同。性能基准代码
这是计时脚本。此处调用的所有函数都在上面定义。
继续阅读
跳转到 Pandas Merging 101 中的其他主题继续学习:
合并基础——连接的基本类型
基于索引的连接
推广到多个 DataFrame
交叉连接*
\* 你在这里