我如何与熊猫执行(INNER|(LEFT|RIGHT|FULL)OUTER)JOIN?如何在合并后为缺少的行添加NaN?合并后如何消除NaN?我可以在索引上合并吗?如何合并多个DataFrame?与熊猫交叉连接合并参加凹面?使现代化谁什么为什么?

…等等。我看到了这些反复出现的问题,这些问题涉及熊猫合并功能的各个方面。今天,关于合并及其各种用例的大部分信息都分散在数十篇措辞糟糕、无法搜索的帖子中。这里的目的是为后人整理一些更重要的观点。

这篇问答旨在成为一系列关于熊猫常用习惯用法的有用用户指南的下一篇(请参阅这篇关于旋转的文章和这篇关于串联的文章,稍后我将对此进行讨论)。

请注意,这篇文章并不是用来替代文档的,所以请同时阅读!其中一些例子就是从那里得到的。


目录

为了方便访问。

合并基础知识-连接的基本类型(请先阅读)基于索引的联接推广到多个数据帧交叉联接


当前回答

我认为你应该在解释中包括这一点,因为这是我经常看到的相关合并,我认为这被称为交叉连接。这是一个合并,当唯一的df不共享任何列时发生,它只是并排合并2个dfs:

设置:

names1 = [{'A':'Jack', 'B':'Jill'}]

names2 = [{'C':'Tommy', 'D':'Tammy'}]

df1=pd.DataFrame(names1)
df2=pd.DataFrame(names2)
df_merged= pd.merge(df1.assign(X=1), df2.assign(X=1), on='X').drop('X', 1)

这将创建一个虚拟X列,在X上合并,然后将其放置以生成

数据_合并:

      A     B      C      D
0  Jack  Jill  Tommy  Tammy

其他回答

本文将介绍以下主题:

如何正确地推广到多个DataFrame(以及为什么合并有缺点)在唯一密钥上合并在非唯一密钥上合并

回到顶部



推广到多个数据帧

通常,当多个数据帧要合并在一起时,就会出现这种情况。实际上,这可以通过链接合并调用来实现:

df1.merge(df2, ...).merge(df3, ...)

然而,对于许多DataFrame来说,这很快就失控了。此外,可能需要对未知数量的数据帧进行概括。

在这里,我介绍了pd.concat用于在唯一键上的多路连接,以及DataFrame.join用于在非唯一键上进行多路连接。首先,设置。

# Setup.
np.random.seed(0)
A = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'valueA': np.random.randn(4)})    
B = pd.DataFrame({'key': ['B', 'D', 'E', 'F'], 'valueB': np.random.randn(4)})
C = pd.DataFrame({'key': ['D', 'E', 'J', 'C'], 'valueC': np.ones(4)})
dfs = [A, B, C] 

# Note: the "key" column values are unique, so the index is unique.
A2 = A.set_index('key')
B2 = B.set_index('key')
C2 = C.set_index('key')

dfs2 = [A2, B2, C2]

对唯一键进行多路合并

如果您的键(这里,键可以是列或索引)是唯一的,那么您可以使用pd.concat。请注意,pd.conct在索引上加入DataFrames。

# Merge on `key` column. You'll need to set the index before concatenating
pd.concat(
    [df.set_index('key') for df in dfs], axis=1, join='inner'
).reset_index()

  key    valueA    valueB  valueC
0   D  2.240893 -0.977278     1.0

# Merge on `key` index.
pd.concat(dfs2, axis=1, sort=False, join='inner')

       valueA    valueB  valueC
key                            
D    2.240893 -0.977278     1.0

对于完全外部联接,省略join='inner'。请注意,不能指定LEFT或RIGHT OUTER联接(如果需要,请使用下面描述的联接)。


对具有重复项的关键点进行多路合并

concat速度快,但也有缺点。它无法处理重复项。

A3 = pd.DataFrame({'key': ['A', 'B', 'C', 'D', 'D'], 'valueA': np.random.randn(5)})
pd.concat([df.set_index('key') for df in [A3, B, C]], axis=1, join='inner')
ValueError: Shape of passed values is (3, 4), indices imply (3, 2)

在这种情况下,我们可以使用join,因为它可以处理非唯一键(请注意,join在数据帧的索引上连接数据帧;除非另有规定,否则它在后台调用merge并执行LEFT OUTER join)。

# Join on `key` column. Set as the index first.
# For inner join. For left join, omit the "how" argument.
A.set_index('key').join([B2, C2], how='inner').reset_index()

  key    valueA    valueB  valueC
0   D  2.240893 -0.977278     1.0

# Join on `key` index.
A3.set_index('key').join([B2, C2], how='inner')

       valueA    valueB  valueC
key                            
D    1.454274 -0.977278     1.0
D    0.761038 -0.977278     1.0


继续阅读

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

合并基础知识-连接的基本类型基于索引的联接推广到多个数据帧*交叉联接

*你在这里

连接101

这些动画可能更能直观地解释您。信贷:Garrick Aden Buie tidyexplain repo

内部联接

外部联接或完全联接

右联接

左联接

pd.contat([df0,df1],kwargs)的补充视觉视图。注意,kwargaxis=0或axis=1的含义不像df.min()或df.apply(func)那样直观


本文将介绍以下主题:

不同条件下的索引合并基于索引的联接的选项:合并、联接、连接合并索引合并一个索引,另一个列有效使用命名索引简化合并语法

回到顶部



基于索引的联接

TL;博士

有几个选项,有些比其他选项更简单,具体取决于用途案例使用left_index和right_index的DataFrame.merge(或使用命名索引的left_on和right_on)支持内部/左侧/右侧/完整一次只能加入两个支持列列、索引列、索引索引联接DataFrame.join(加入索引)支持内部/左侧(默认)/右侧/完整一次可以连接多个DataFrame支持索引索引联接pd.concat(索引上的联接)支持内部/完整(默认)一次可以连接多个DataFrame支持索引索引联接


索引到索引联接

设置和基础知识

import pandas as pd
import numpy as np

np.random.seed([3, 14])
left = pd.DataFrame(data={'value': np.random.randn(4)}, 
                    index=['A', 'B', 'C', 'D'])    
right = pd.DataFrame(data={'value': np.random.randn(4)},  
                     index=['B', 'D', 'E', 'F'])
left.index.name = right.index.name = 'idxkey'

left
           value
idxkey          
A      -0.602923
B      -0.402655
C       0.302329
D      -0.524349

right
 
           value
idxkey          
B       0.543843
D       0.013135
E      -0.326498
F       1.385076

通常,索引上的内部联接如下所示:

left.merge(right, left_index=True, right_index=True)

         value_x   value_y
idxkey                    
B      -0.402655  0.543843
D      -0.524349  0.013135

其他联接遵循类似的语法。

值得注意的替代方案

DataFrame.join默认为索引上的联接。默认情况下,DataFrame.join执行LEFT OUTER join,因此how='inner'在这里是必要的。left.join(right,how='inner',lsuffix='_x',rsuffix='_y')值_x值_yidx键B-0.402655 0.543843D-0.524349 0.013135注意,我需要指定lsuffix和rsuffix参数,否则join将出错:left.join(右)ValueError:列重叠,但未指定后缀:Index(['value'],dtype='object')因为列名相同。如果它们的名称不同,这不会是一个问题。left.rename(columns={‘value‘:‘left value‘}).join(right,how=‘inner‘)左值idx键B-0.402655 0.543843D-0.524349 0.013135pd.concat在索引上连接,可以同时连接两个或多个DataFrame。默认情况下,它执行完全外部联接,因此此处需要how='inner'。。pd.contat([left,right],axis=1,sort=False,join='inner')价值,价值idx键B-0.402655 0.543843D-0.524349 0.013135有关concat的更多信息,请参阅本文。


索引到列连接

要使用左索引、右列索引执行内部联接,您将使用DataFrame.merge组合left_index=True和right_on=。。。。

right2 = right.reset_index().rename({'idxkey' : 'colkey'}, axis=1)
right2
 
  colkey     value
0      B  0.543843
1      D  0.013135
2      E -0.326498
3      F  1.385076

left.merge(right2, left_index=True, right_on='colkey')

    value_x colkey   value_y
0 -0.402655      B  0.543843
1 -0.524349      D  0.013135

其他连接遵循类似的结构。请注意,只有合并才能执行索引到列的连接。如果左侧的索引级别数等于右侧的列数,则可以连接多个列。

join和concat不能混合合并。您需要使用DataFrame.set_index将索引设置为预步骤。


有效使用命名索引[熊猫>=0.23]

如果索引已命名,则从panda>=0.23开始,DataFrame.merge允许您将索引名称指定为on(或根据需要指定left_on和right_on)。

left.merge(right, on='idxkey')

         value_x   value_y
idxkey                    
B      -0.402655  0.543843
D      -0.524349  0.013135

对于前面的合并索引为left、列为right的示例,可以使用索引名为left的left_on:

left.merge(right2, left_on='idxkey', right_on='colkey')

    value_x colkey   value_y
0 -0.402655      B  0.543843
1 -0.524349      D  0.013135


继续阅读

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

合并基础知识-连接的基本类型基于索引的联接*推广到多个数据帧交叉联接

*你在这里

我认为你应该在解释中包括这一点,因为这是我经常看到的相关合并,我认为这被称为交叉连接。这是一个合并,当唯一的df不共享任何列时发生,它只是并排合并2个dfs:

设置:

names1 = [{'A':'Jack', 'B':'Jill'}]

names2 = [{'C':'Tommy', 'D':'Tammy'}]

df1=pd.DataFrame(names1)
df2=pd.DataFrame(names2)
df_merged= pd.merge(df1.assign(X=1), df2.assign(X=1), on='X').drop('X', 1)

这将创建一个虚拟X列,在X上合并,然后将其放置以生成

数据_合并:

      A     B      C      D
0  Jack  Jill  Tommy  Tammy