这篇文章的内容原本是想成为《Pandas合并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
计算这个结果最有效的方法是什么?
3条答案
按热度按时间kxeu7u2r1#
让我们从建立一个基准开始。解决此问题的最简单方法是使用临时“键”列:
其工作原理是,为两个 Dataframe 分配一个具有相同值(例如,1)的临时“键”列。
merge
然后在“键”上执行多对多连接。虽然多对多连接技巧适用于大小合理的 Dataframe ,但在较大的数据上,您会看到相对较低的性能。
更快的实现需要numpy。下面是一些著名的一维笛卡尔积的numpy实现。我们可以利用其中一些高性能的解决方案来获得我们想要的输出。然而,我最喜欢的是@senderle的第一个实现。
泛化:唯一或非唯一索引 Dataframe 上的交叉连接
免责声明
这些解决方案针对具有非混合标量数据类型的 Dataframe 进行了优化。如果处理混合数据类型,使用风险自负!
这个技巧适用于任何类型的 Dataframe 。我们使用上述公式计算 Dataframe 数值索引的笛卡尔积
cartesian_product
,使用此选项重新索引 Dataframe ,然后同样的道理,
此解决方案可以推广到多个 Dataframe 。例如
进一步简化
不涉及@senderle的更简单的解决方案
cartesian_product
仅处理两个 Dataframe 时,这是可能的。使用np.broadcast_arrays
,我们可以达到几乎相同的性能水平。性能比较
在一些具有唯一索引的人工 Dataframe 上对这些解决方案进行基准测试
请注意,计时可能会因您的设置、数据和选择而有所不同
cartesian_product
助手功能(如适用)。性能基准代码
这是计时脚本。这里调用的所有函数都在上面定义。
继续阅读
跳转到101中的其他主题继续学习:
合并基础-连接的基本类型
基于索引的联接
推广到多个 Dataframe
交叉连接*
6vl6ewon2#
Pandas1.2.0之后
merge
现在有选择了cross
```left.merge(right, how='cross')
import itertools
l=list(itertools.product(left.values.tolist(),right.values.tolist()))
pd.DataFrame(list(map(lambda x : sum(x,[]),l)))
0 1 2 3
0 A 1 X 20
1 A 1 Y 30
2 A 1 Z 50
3 B 2 X 20
4 B 2 Y 30
5 B 2 Z 50
6 C 3 X 20
7 C 3 Y 30
8 C 3 Z 50
e5nqia273#
这里有一个三重的方法
concat
```m = pd.concat([pd.concat([left]*len(right)).sort_index().reset_index(drop=True),
pd.concat([right]*len(left)).reset_index(drop=True) ], 1)
0 A 1 X 20
1 A 1 Y 30
2 A 1 Z 50
3 B 2 X 20
4 B 2 Y 30
5 B 2 Z 50
6 C 3 X 20
7 C 3 Y 30
8 C 3 Z 50