熊猫合并101

新手上路,请多包涵
  • How can I perform a ( INNER | ( LEFT | RIGHT | FULL ) OUTER ) JOIN 与熊猫?
  • 如何在合并后为缺失的行添加 NaN?
  • 合并后如何摆脱 NaN?
  • 我可以合并索引吗?
  • 如何合并多个 DataFrame?
  • 与熊猫交叉加入
  • merge ? join ? concat ? update ?谁?什么?为什么?!

… 和更多。我已经看到这些反复出现的问题询问熊猫合并功能的各个方面。今天,关于合并及其各种用例的大部分信息都分散在几十个措辞不当、无法搜索的帖子中。这里的目的是为后代整理一些更重要的观点。

本问答旨在成为有关常见 pandas 习语的一系列有用用户指南的下一部分(请参阅 这篇关于 pivoting 的文章和 关于 concatenation 的这篇文章,我稍后会谈到)。

请注意,这篇文章 并不是 要替代 文档,所以也请阅读!一些例子取自那里。


目录

为了方便访问。

原文由 cs95 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 784
2 个回答

这篇文章旨在为读者提供 SQL 风格与 Pandas 合并的入门知识,如何使用它以及何时不使用它。

特别是,本文将介绍以下内容:

  • 基础 - 连接类型(左、右、外、内)

    • 合并不同的列名
    • 与多列合并
    • 避免输出中出现重复的合并键列

这篇文章(以及我在这个线程上的其他帖子)不会经过:

  • 与性能相关的讨论和时间安排(目前)。在适当的情况下,主要提到了更好的替代方案。
  • 处理后缀、删除额外列、重命名输出和其他特定用例。还有其他(阅读:更好的)帖子可以解决这个问题,所以弄清楚吧!

注意 大多数示例在演示各种功能时默认为 INNER JOIN 操作,除非另有说明。

此外,这里的所有 DataFrame 都可以复制和复制,以便您可以使用它们。此外,请参阅 这篇关于如何从剪贴板读取 DataFrames 的帖子

最后,JOIN 操作的所有视觉表示都是使用 Google 绘图手绘的。灵感来自 这里



说得够多了 - 告诉我如何使用 merge

设置和基础

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 s 的缺失值

要执行 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

这仅返回来自 leftright 的行,它们共享一个公共密钥(在本例中为“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' ,则仅使用来自 left 的键,并且来自 right 的缺失数据被替换为 NaN。

同样,对于 RIGHT OUTER JOIN 或 RIGHT JOIN 是…

…指定 how='right'

 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

在这里,使用来自 right left 缺失数据被替换为 NaN。

最后,对于 FULL OUTER JOIN ,由

指定 how='outer'

 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。

该文档很好地总结了这些各种合并:

在此处输入图像描述


其他 JOIN - LEFT-Excluding、RIGHT-Excluding 和 FULL-Excluding/ANTI JOIN

如果您需要 LEFT-Excluding JOINRIGHT-Excluding JOIN 分两步。

对于 LEFT-Excluding JOIN,表示为

首先执行 LEFT OUTER JOIN,然后过滤来自 left 的行(不包括右边的所有内容),

 (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-Excluding 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


键列的不同名称

If the key columns are named differently—for example, left has keyLeft , and right has keyRight instead of key —那么您必须指定 left_onright_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


避免输出中的重复键列

When merging on keyLeft from left and keyRight from right , if you only want either of the keyLeft or 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 操作时可能很重要。


仅合并来自 DataFrames 之一的单列

例如,考虑

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,则性能更高的解决方案将涉及 map

 # 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_onright_on ,视情况而定)。

 left.merge(right, on=['key1', 'key2'] ...)

或者,如果名称不同,

 left.merge(right, left_on=['lkey1', 'lkey2'], right_on=['rkey1', 'rkey2'])


其他有用 merge* 操作和功能

本节仅涵盖最基本的内容,旨在激发您的胃口。有关更多示例和案例,请参阅 mergejoinconcat 的文档 以及函数规范的链接。



继续阅读

跳转到 Pandas Merging 101 中的其他主题继续学习:

*你在这里。

原文由 cs95 发布,翻译遵循 CC BY-SA 4.0 许可协议

pd.concat([df0, df1], kwargs) 的补充视觉视图。请注意,kwarg axis=0axis=1 的含义不如 df.mean()df.apply(func) 直观


在 pd.concat([df0, df1])

原文由 eliu 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题