这篇文章旨在向读者介绍SQL风格的与Pandas的合并,如何使用它,以及何时不使用它。
特别是,这篇文章将经历以下内容:
基础知识-连接类型(左、右、外、内)使用不同的列名合并合并多个列避免输出中出现重复的合并键列
这篇帖子(以及我在这篇帖子上的其他帖子)不会经历什么:
与绩效相关的讨论和时间安排(目前)。最值得注意的是,在适当的情况下,提到了更好的替代方案。处理后缀、删除额外列、重命名输出和其他特定用例。还有其他(读:更好)的帖子可以解决这个问题,所以好好想想吧!
笔记除非另有规定,大多数示例在演示各种功能时默认使用INNER JOIN操作。此外,可以复制和复制此处的所有数据帧你可以和他们一起玩。另外,请参见邮递如何从剪贴板读取DataFrames。最后,JOIN操作的所有可视化表示都是使用GoogleDrawings手工绘制的。灵感来自这里。
说得够多了-告诉我如何使用合并!
设置和基础知识
np.random.seed(0)
left = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'value': np.random.randn(4)})
right = pd.DataFrame({'key': ['B', 'D', 'E', 'F'], 'value': np.random.randn(4)})
left
key value
0 A 1.764052
1 B 0.400157
2 C 0.978738
3 D 2.240893
right
key value
0 B 1.867558
1 D -0.977278
2 E 0.950088
3 F -0.151357
为了简单起见,键列具有相同的名称(目前)。
INNER JOIN表示为
笔记这一点以及即将公布的数字都遵循这一惯例:蓝色表示合并结果中存在的行红色表示从结果中排除的行(即已删除)绿色表示结果中缺少用NaN替换的值
要执行INNER JOIN,请在左侧DataFrame上调用merge,将右侧DataFrame和连接键(至少)指定为参数。
left.merge(right, on='key')
# Or, if you want to be explicit
# left.merge(right, on='key', how='inner')
key value_x value_y
0 B 0.400157 1.867558
1 D 2.240893 -0.977278
这只返回共享一个公共键(在本例中为“B”和“D”)的左右行。
LEFT OUTER JOIN或LEFT JOIN由
这可以通过指定how='left'来执行。
left.merge(right, on='key', how='left')
key value_x value_y
0 A 1.764052 NaN
1 B 0.400157 1.867558
2 C 0.978738 NaN
3 D 2.240893 -0.977278
仔细注意此处NaN的位置。如果指定how='left',则只使用左侧的键,右侧缺失的数据将被NaN替换。
同样,对于RIGHT OUTER JOIN或RIGHT JOIN,它是。。。
…指定如何=“正确”:
left.merge(right, on='key', how='right')
key value_x value_y
0 B 0.400157 1.867558
1 D 2.240893 -0.977278
2 E NaN 0.950088
3 F NaN -0.151357
这里,使用右边的键,左边缺失的数据用NaN替换。
最后,对于FULL OUTER JOIN,由
指定how=“外部”。
left.merge(right, on='key', how='outer')
key value_x value_y
0 A 1.764052 NaN
1 B 0.400157 1.867558
2 C 0.978738 NaN
3 D 2.240893 -0.977278
4 E NaN 0.950088
5 F NaN -0.151357
这将使用两个帧中的关键帧,并为两帧中缺少的行插入NaN。
文档很好地总结了这些不同的合并:
其他联接-左排除、右排除和全排除/反联接
如果需要两个步骤中的LEFT Exclusive JOIN和RIGHT Exclusive JOINs。
对于LEFT Exclude JOIN,表示为
首先执行LEFT OUTER JOIN,然后过滤到仅来自左侧的行(不包括来自右侧的所有行),
(left.merge(right, on='key', how='left', indicator=True)
.query('_merge == "left_only"')
.drop('_merge', 1))
key value_x value_y
0 A 1.764052 NaN
2 C 0.978738 NaN
哪里
left.merge(right, on='key', how='left', indicator=True)
key value_x value_y _merge
0 A 1.764052 NaN left_only
1 B 0.400157 1.867558 both
2 C 0.978738 NaN left_only
3 D 2.240893 -0.977278 both
同样,对于RIGHT Exclusive JOIN,
(left.merge(right, on='key', how='right', indicator=True)
.query('_merge == "right_only"')
.drop('_merge', 1))
key value_x value_y
2 E NaN 0.950088
3 F NaN -0.151357
最后,如果需要执行只保留左键或右键而不同时保留两者的合并(IOW,执行ANTI-JOIN),
你可以用类似的方式-
(left.merge(right, on='key', how='outer', indicator=True)
.query('_merge != "both"')
.drop('_merge', 1))
key value_x value_y
0 A 1.764052 NaN
2 C 0.978738 NaN
4 E NaN 0.950088
5 F NaN -0.151357
键列的不同名称
如果键列的名称不同,例如,left有keyLeft,right有keyRight而不是key,则必须将left_on和right_on指定为参数而不是on:
left2 = left.rename({'key':'keyLeft'}, axis=1)
right2 = right.rename({'key':'keyRight'}, axis=1)
left2
keyLeft value
0 A 1.764052
1 B 0.400157
2 C 0.978738
3 D 2.240893
right2
keyRight value
0 B 1.867558
1 D -0.977278
2 E 0.950088
3 F -0.151357
left2.merge(right2, left_on='keyLeft', right_on='keyRight', how='inner')
keyLeft value_x keyRight value_y
0 B 0.400157 B 1.867558
1 D 2.240893 D -0.977278
避免输出中的重复键列
在从左侧合并keyLeft和从右侧合并keyRight时,如果只希望输出中包含keyLeft或keyRight(但不同时包含两者),则可以首先将索引设置为初步步骤。
left3 = left2.set_index('keyLeft')
left3.merge(right2, left_index=True, right_on='keyRight')
value_x keyRight value_y
0 0.400157 B 1.867558
1 2.240893 D -0.977278
与前面命令的输出(即left2.merge的输出(right2,left_on='keyLeft',right_on='keyRight',how='inner')相比,您会发现缺少keyLeft。您可以根据将哪个帧的索引设置为关键帧来确定要保留哪个列。例如,当执行一些OUTER JOIN操作时,这可能很重要。
仅合并其中一个DataFrame中的一列
例如,考虑
right3 = right.assign(newcol=np.arange(len(right)))
right3
key value newcol
0 B 1.867558 0
1 D -0.977278 1
2 E 0.950088 2
3 F -0.151357 3
如果您只需要合并“newcol”(没有任何其他列),则通常可以在合并之前仅对列进行子集:
left.merge(right3[['key', 'newcol']], on='key')
key value newcol
0 B 0.400157 0
1 D 2.240893 1
如果您正在执行LEFT OUTER JOIN,则更高性能的解决方案将涉及映射:
# left['newcol'] = left['key'].map(right3.set_index('key')['newcol']))
left.assign(newcol=left['key'].map(right3.set_index('key')['newcol']))
key value newcol
0 A 1.764052 NaN
1 B 0.400157 0.0
2 C 0.978738 NaN
3 D 2.240893 1.0
如上所述,这类似于,但比
left.merge(right3[['key', 'newcol']], on='key', how='left')
key value newcol
0 A 1.764052 NaN
1 B 0.400157 0.0
2 C 0.978738 NaN
3 D 2.240893 1.0
合并多个列
要在多个列上连接,请为on(或left_on和right_on,视情况而定)指定一个列表。
left.merge(right, on=['key1', 'key2'] ...)
或者在名称不同的情况下,
left.merge(right, left_on=['lkey1', 'lkey2'], right_on=['rkey1', 'rkey2'])
其他有用的合并*操作和功能
将DataFrame与索引上的Series合并:请参阅此答案。除了合并,在某些情况下,还使用DataFrame.update和DataFrame.combine_first来更新一个DataFrame与另一个DataFrame。pd.merge_ordered是有序JOIN的一个有用函数。pd.merge_asof(读:merge_asof)对于近似连接很有用。
本节仅介绍最基本的内容,目的仅在于刺激您的食欲。有关更多示例和案例,请参阅关于合并、联接和连接的文档以及函数规范的链接。
继续阅读
跳转到Pandas Merging 101中的其他主题继续学习:
合并基础知识-连接的基本类型*基于索引的联接推广到多个数据帧交叉联接
*你在这里。