目录

前言一、回顾Numpy数组的合并二、concat方法合并DataFrame对象三、append方法的使用四、merge方法合并DataFrame对象(一)比较merge与concat(二)参数on、left_on和right_on的用法(三)合并时四种不同的连接规则(四)left_index与right_index参数的用法

五、join方法的使用六、小结

前言

合并是指把两个甚至多个 DataFrame 对象连接起来,与合并相关的方法有四个:concat,append,merge,join。

它们的主要区别:

concat支持多个 DataFrame 对象的水平和垂直排放,即可以列合并也可以行合并;但与merge不同,它的合并不基于列值匹配。append只能行合并,与concat做行合并相比,形式更为简化。merge的合并是列合并,合并时会基于列值匹配,类似于 SQL 语言的多表连接查询;merge只能对两个 DataFrame 对象同时合并。join也是列合并,但它的合并不是基于列值匹配而是基于行索引/列索引的匹配,特定情况下与concat做列合并的效果相当。

import pandas as pd

import numpy as np

一、回顾Numpy数组的合并

Numpy 数组的合并使用np.concatenate()方法。

1、多个一维列表合并的情形

x = [1, 2, 3]

y = [4, 5, 6]

z = [7, 8, 9]

np.concatenate([x, y, z]) # 因为x、y和z都是一维的,所以合并以后也是一维的

array([1, 2, 3, 4, 5, 6, 7, 8, 9])

2、二维Numpy数组合并的情形

m = np.array([[1,2],[3,4]])

n = np.array([[5,6],[7,8]])

p = np.array([[9,10],[11,12]])

# 默认是按行方向合并,相当于axis=0

np.concatenate([m,n,p])

array([[ 1, 2],

[ 3, 4],

[ 5, 6],

[ 7, 8],

[ 9, 10],

[11, 12]])

np.vstack((m,n,p)) # 等价于np.concatenate([m,n,p],axis=0)

array([[ 1, 2],

[ 3, 4],

[ 5, 6],

[ 7, 8],

[ 9, 10],

[11, 12]])

如果按列合并,必须使用axis=1参数。

np.concatenate([m,n,p],axis=1)

array([[ 1, 2, 5, 6, 9, 10],

[ 3, 4, 7, 8, 11, 12]])

np.hstack((m,n,p)) # 等价于np.concatenate([m,n,p],axis=1)

array([[ 1, 2, 5, 6, 9, 10],

[ 3, 4, 7, 8, 11, 12]])

二、concat方法合并DataFrame对象

np.concatenate与pd.concat最主要的差异就是 Pandas 合并时会保留索引,并且允许索引是重复的。

pd.concat既可以行合并,也可以列合并;并且沿着哪个轴合并,合并对象上该轴的索引将全部保留;例如按行合并(对应于axis=0),此时参与合并的所有 DataFrame 对象的行索引则全部保留,并且由上到下按序排列。

而另一轴的索引取决于join参数是'outer'还是'inner',前者做并集后者做交集;例如当按行合并(对应于axis=0)时,另一轴的索引是指列索引,结果的列索引将由参与合并的所有 DataFrame 对象的列索引做并集(对应于join='outer')或做交集(对应于join='outer')而得到

pd.concat()方法原型: pd.concat(objs, axis=0, join='outer', ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False, copy=True)

objs:要连接的 pandas 对象列表或字典。axis:指定连接的轴,0 表示按行连接,1 表示按列连接。join:指定连接方式,‘inner’ 表示取交集,‘outer’ 表示取并集。ignore_index:如果为 True,则忽略原始索引,生成新的连续索引。keys:使用层次化索引进行连接。levels:如果 keys 参数被指定,则 levels 参数表示索引层级。names:如果 keys 参数被指定,则 names 参数表示索引名称。verify_integrity:如果为 True,则检查结果对象是否包含重复索引。sort:如果为 True,则按索引进行排序。copy:如果为 False,则不复制数据。

df1 = pd.DataFrame({'A':['A1','A2'],'B':['B1','B2'],'C':['C1','C2']},index=[1,2])

df1

df2 = pd.DataFrame({'A':['A3','A4'],'B':['B3','B4'],'D':['D3','D4']},index=[1,3])

df2

没有axis=0或者明确给出axis=0,都是按行合并,此时列索引取并集。

pd.concat([df1,df2])

明确给出axis=0,则是按列合并,此时行索引取并集。

pd.concat([df1,df2],axis=1)

之所以上面两个例子都是并集,原因在于concat的join参数默认值是'outer',表示取并集(类似于SQL的外连接);而当明确指明join='inner'时,将取交集计算结果(类似于SQL的内连接)。

当join='inner'时,按行合并,则列索引取交集。

pd.concat([df1,df2],join='inner')

补充:ignore_index参数的使用:

ignore_index=True会忽略原来的行索引,使用新的位置索引。

pd.concat([df1,df2],join='inner',ignore_index=True)

当join='inner'时,按列合并,则行索引取交集。

pd.concat([df1,df2],axis=1,join='inner')

三、append方法的使用

append可以把两个 DataFrame 对象按行合并,其功能等价于上面讲的pd.concat([df1,df2])。

df.append()方法原型: DataFrame.append(other, ignore_index=False, verify_integrity=False, sort=None)

other:可以是 DataFrame、Series 或者包含 DataFrame 或 Series 的列表,表示要附加到原始 DataFrame 的数据。ignore_index:如果为 True,则忽略附加的数据的索引,并为结果 DataFrame 分配一个新的整数索引。默认为 False。verify_integrity:如果为 True,则在附加操作之前检查结果 DataFrame 中的新索引是否唯一。如果新索引不唯一,则会引发 ValueError。默认为 False。sort:如果为 True,则对结果 DataFrame 进行排序。默认为 None,表示不进行排序。

df1.append(df2)

如果要使用append方法为df1对象增加记录行,需要把要增加的记录行构成df2,并且写成如下形式:df1=df1.append(df2)。上面语句之所以要赋值,是因为 Pandas 中的append不会直接修改原始的df1对象。

四、merge方法合并DataFrame对象

(一)比较merge与concat

df3 = pd.DataFrame({'employee': ['Bob', 'Jake', 'Lisa', 'Sue'],

'group': ['Accounting', 'Engineering', 'Engineering', 'HR']})

df3

df4 = pd.DataFrame({'employee': ['Lisa', 'Bob', 'Jake', 'Sue'],

'hire_date': [2004, 2008, 2012, 2014]})

df4

下面的示例比较merge与concat,可以看出:

(1)merge主要基于列值匹配而进行列合并,类似于SQL中的连接操作,而concat并没有基于列值匹配进行合并。

(2)merge中的两个合并对象只用逗号分隔,而concat中的两个合并对象要构成列表。

一对一连接:在起连接作用的关键列(employee)上,通过列值匹配进行合并。

pd.merge(df3, df4)

concat并没有基于两个employee列的相同值匹配进行合并。

pd.concat([df3,df4],axis=1)

df5 = pd.DataFrame({'group': ['Accounting', 'Accounting',

'Engineering', 'Engineering', 'HR', 'HR'],

'skills': ['math', 'spreadsheets', 'coding', 'linux',

'spreadsheets', 'organization']})

df5

pd.merge()方法原型: pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)

left:要合并的左侧 DataFrame。right:要合并的右侧 DataFrame。how:指定要使用的合并方法。可选值包括: ‘left’:保留左侧 DataFrame 中的所有行,并将右侧 DataFrame 中与左侧匹配的行合并到结果中。如果右侧 DataFrame 中没有匹配的行,则将 NaN 填充到结果中的相应位置。 ‘right’:保留右侧 DataFrame 中的所有行,并将左侧 DataFrame 中与右侧匹配的行合并到结果中。如果左侧 DataFrame 中没有匹配的行,则将 NaN 填充到结果中的相应位置。 ‘inner’:保留左右两侧 DataFrame 中都存在的行,并将它们合并到结果中。 ‘outer’:保留左右两侧 DataFrame 中的所有行,并将它们合并到结果中。如果某一侧 DataFrame 中没有匹配的行,则将 NaN 填充到结果中的相应位置。on:指定要合并的列(或列的名称)。如果两个 DataFrame 中的列名相同,并且没有指定该参数,则将这些列作为合并的键。如果要合并的列名不同,可以分别使用left_on和right_on参数指定左右两侧的列名。left_on:指定左侧 DataFrame 中用作合并键的列。right_on:指定右侧 DataFrame 中用作合并键的列。left_index:如果为 True,则使用左侧 DataFrame 的索引作为合并键。right_index:如果为 True,则使用右侧 DataFrame 的索引作为合并键。sort:如果为 True,则对合并后的结果进行排序。suffixes:如果在合并过程中遇到了重叠的列名,则添加到重叠列名的后缀。copy:如果为 False,则不复制数据。默认为 True。indicator:如果为 True,则在结果中添加一个名为 “_merge” 的列,指示每行的合并方式(如 “left_only”、“right_only”、“both”)。validate:验证合并操作的类型。可选值包括:“one_to_one”、“one_to_many”、“many_to_one”、“many_to_many”。

(二)参数on、left_on和right_on的用法

使用on参数显式设置起连接作用的关键列是两个 DataFrame 对象的group列。

pd.merge(df3, df5,on='group')

当两个 DataFrame 的关键列的列名不同时,需要使用left_on和right_on参数实现列值匹配。

df6 = pd.DataFrame({'name': ['Bob', 'Jake', 'Lisa', 'Sue'],

'salary': [70000, 80000, 120000, 90000]})

pd.merge(df3, df6, left_on="employee", right_on="name")

上面合并后employee列和name列是重复的,可以使用drop方法删除多余的name列。

pd.merge(df3, df6, left_on="employee", right_on="name") .drop('name',axis=1)

(三)合并时四种不同的连接规则

重新设置df3包含空数据(NaN)。

df3 = pd.DataFrame({'employee': ['Bob', 'Jake', 'Lisa', 'Sue','Tom'],

'group': ['Accounting', 'Engineering', 'Engineering', 'HR',np.NaN]})

df3 # 注意Tom目前没有所属部门

df7 = pd.DataFrame({'group': ['Accounting', 'Engineering', 'HR','Sale'],

'supervisor': ['Carly', 'Guido', 'Steve','Jack']})

df7

merge默认的连接方式是'inner'(即内连接),基于列值匹配时取交集,或者明确指明连接方式为how='inner',两个数据集能匹配上的记录才会出现在结果中。

pd.merge(df3,df7,how='inner') # 等价于pd.merge(df3,df7)

how='outer'指明连接方式是外连接,此时基于列值匹配时取并集。两个数据集中不匹配的记录也都会出现在结果中(例如下面最后两条记录)。

pd.merge(df3,df7,how='outer')

how='left'指明连接方式是左连接,此时基于列值匹配时会全部保留左边数据集的记录。而右边数据集中不匹配的记录则不会被合并到结果中。

注意:Sale部门因为没有职员与之匹配,所以Sale部门没有出现在结果中。

pd.merge(df3,df7,how='left')

how='right'指明连接方式是右连接,此时基于列值匹配时会全部保留右边数据集的记录。而左边数据集中不匹配的记录则不会被合并到结果中。

注意:职员Tom因为没有部门与之匹配,所以Tom没有出现在结果中。

pd.merge(df3,df7,how='right')

(四)left_index与right_index参数的用法

merge既可以合并列,也可以合并索引,下面先设置employee为两个数据集df3和df4的索引,然后基于该索引进行合并。

df3 = df3.set_index('employee')

df3

df4 = df4.set_index('employee')

df4

基于索引合并就需要使用left_index与right_index参数。

注意:基于索引合并只取交集,而不能指定join参数。

# pd.merge(df3,df4) # 不使用left_index与right_index参数会出错

pd.merge(df3,df4,left_index=True,right_index=True)

五、join方法的使用

df1

df2

df.join()方法原型: DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)

other:要连接的另一个 DataFrame 或 Series 对象。on:指定连接的列名或索引级别。如果为 None,则默认使用索引进行连接。how:指定连接方式,默认为左连接(‘left’),可选值包括 ‘left’, ‘right’, ‘outer’, ‘inner’。lsuffix:左侧 DataFrame 列名后缀,用于解决重叠的情况。rsuffix:右侧 DataFrame 列名后缀,用于解决重叠的情况。sort:如果为 True,则根据连接键对结果进行排序。

join方法就是基于索引进行的列合并,如果两个数据集有重复的列名,需指定lsuffix,rsuffix参数。 join方法默认是左连接(how='left'),只保留左边的全部记录,对列除了加后缀不做处理,直接水平方向合并在一起。

df1.join(df2,lsuffix='_l', rsuffix='_r')

当连接方式how='outer'时,等价于axis=1时的concat合并。

df1.join(df2,lsuffix='_l', rsuffix='_r',how='outer')

pd.concat([df1,df2],axis=1) # 与上面等价

六、小结

concat默认的合并方式是行拼接,取并集(axis=0,join='outer');

merge默认的合并方式是基于列值进行列拼接,取交集(how='inner');

join默认的合并方式是基于行索引进行列合并,并且默认为左连接。

相关文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: