以下内容转载自https://blog.csdn.net/weixin_42782150/article/details/89546357?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-4&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-4
Pandas提供了concat,merge,join和append四种方法用于dataframe的拼接,其区别如下:
函数 | 适用场景 | 调用方法 | 备注 |
---|---|---|---|
.concat() | 可用于两个或多个df间行方向(增加行,下同)或列方向(增加列,下同)进行内联或外联拼接操作,默认行拼接,取并集 | result = pd.concat ( [df1,df4], axis=1 ) |
提供了参数axis设置行/列拼接的方向 |
.merge() | 可用于两个df间行方向(一般用join代替)或列方向的拼接操作,默认列拼接,取交集(即:存在相同主键的df1和df2的列拼接) | result=pd.merge (df1, df2,how=‘left’) |
提供了类似于SQL数据库连接操作的功能,支持左联、右联、内联和外联等全部四种SQL连接操作类型 |
.join() | 可用于df间列方向的拼接操作,默认左列拼接,how=’left’ | df1.join(df2) | 支持左联、右联、内联和外联四种操作类型 |
.append() | 可用于df间行方向的拼接操作,默认 |
pandas.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=None, copy=True)
objs:series,dataframe或者是panel对象构成的序列lsit
axis:指明连接的轴向, {0/’index’(行), 1/’columns’(列)},默认为0
join:指明连接方式 , {‘inner’(交集), ‘outer(并集)’},默认为outer
join_axes:自定义的索引。指明用其他n-1条轴的索引进行拼接, 而非默认join =’ inner’或’outer’方式拼接
keys:创建层次化索引。可以是任意值的列表或数组、元组数组、数组列表(如果将levels设置成多级数组的话)
ignore_index=True:重建索引
两个DataFrame通过pd.concat()
,既可实现行拼接又可实现列拼接,默认axis=0
,join='outer'
。表df1和df2的行索引(index)和列索引(columns)均可以重复。
join='outer'
,只是沿着一条轴,单纯将多个对象拼接到一起,类似数据库中的全连接(union all)。pd.concat([df1,df2])
,拼接表的index=index(df1) + index(df2),拼接表的columns=columns(df1) ∪ columns(df2),缺失值填充NaN。pd.concat([df1,df2],axis=1)
,拼接表的index=index(df1) ∪ index(df2),拼接表的columns=columns(df1) + columns(df2),缺失值填充NaN。pd.concat([obj1, obj2])
与obj1.append(obj2)
的效果是相同的,使用参数key可以为每个数据集(bj1, obj2)指定块标记;pd.concat([obj1, obj2], axis=1)
与pd.merge(obj1, obj2, left_index=True, right_index=True, how='outer')
的效果是相同的。join='inner'
,拼接方式为“交联”,即:行拼接时,仅保留df1和df2列索引重复的列;列拼接时,仅保留df1和df2行索引重复的行。pd.concat([df1,df4],join='inner')
,拼接表的index=index(df1) + index(df2),拼接表的columns=columns(df1) ∩ columns(df2);pd.concat([df1,df4],axis=1,join='inner')
,拼接表的index=index(df1) ∩ index(df2),拼接表的columns=columns(df1) + columns(df2);a.列名(columns)相同,行索引(index)无重复项的表df1、df2、df3实现行拼接:
import numpy as np
import pandas as pd
#样集1
df1=pd.DataFrame({
'A':['A0','A1','A2','A3'],'B':['B0','B1','B2','B3'],
'C':['C0','C1','C2','C3'],'D':['D0','D1','D2','D3']},
index=[0,1,2,3])
#样集2
df2=pd.DataFrame({
'A':['A4','A5','A6','A7'],'B':['B4','B5','B6','B7'],
'C':['C4','C5','C6','C7'],'D':['D4','D5','D6','D7']},
index=[4,5,6,7])
#样集3
df3=pd.DataFrame({
'A':['A8','A9','A10','A11'],'B':['B8','B9','B10','B11'],
'C':['C8','C9','C10','C11'],'D':['D8','D9','D10','D11']},
index=[8,9,10,11])
#样集4
df4=pd.DataFrame({
'B':['B2','B3','B6','B7'],'D':['D2','D3','D6','D7'],
'F':['F2','F3','F6','F7']},index=[2,3,6,7])
#样集1、2、3、4详见图1.1(a)
#列名(columns)相同,行索引(index)无重复项的表df1、df2、df3实现行拼接
frames = [df1, df2, df3]
pd.concat(frames) #效果见图1.1(b)
#使用参数key可以为每个数据集指定块标记
pd.concat(frames,keys=[ 'x','y','z' ]) #效果见图1.1(c)
得到的行拼接效果如图1.1所示:
b.列名(columns)和行索引(index)均有重复的表df1、df4实现行/列拼接(默认‘join=outer’):
## 使用concat()实现df1、df4行拼接
result = pd.concat( [df1,df4] ) #效果见图1.2(b)
#使用concat()实现df1、df4列拼接
result = pd.concat( [df1,df4] , axis=1 ) #效果见图1.2(c)
c.列名(columns)和行索引(index)均有重复的表df1、df4实现行/列拼接(设置‘join=inner’):
#concat修改join='inner',只保留重复列索引的行拼接
result=pd.concat([df1,df4],join='inner') #效果见图1.3(b)
#concat修改join='inner',只保留重复行索引的列拼接
result=pd.concat([df1,df4],axis=1,join='inner') #效果见图1.3(c)
#利用参数join_axes=[df1.index]指定concat按照df1的行索引进行列拼接,df2仅保留行索引与df1重复的部分
result=pd.concat( [df1,df4],axis=1,join_axes=[df1.index] ) #效果见图1.3(d)
得到的列拼接效果如图1.3所示:
DataFrame.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和right:两个不同的DataFrame或Series
how:连接方式,有inner、left、right、outer,默认为inner
on:用于连接的列索引名称,必须同时存在于左、右两个DataFrame中,默认是以两个DataFrame列名的交集作为连接键,若要实现多键连接,‘on’参数后传入多键列表即可
left_on:左侧DataFrame中用于连接键的列名,这个参数在左右列名不同但代表的含义相同时非常有用;
right_on:右侧DataFrame中用于连接键的列名
left_index:使用左侧DataFrame中的行索引作为连接键( 但是这种情况下最好用JOIN)
right_index:使用右侧DataFrame中的行索引作为连接键( 但是这种情况下最好用JOIN)
sort:默认为False,将合并的数据进行排序,设置为False可以提高性能
suffixes:字符串值组成的元组,用于指定当左右DataFrame存在相同列名时在列名后面附加的后缀名称,默认为(’_x’, ‘_y’)
copy:默认为True,总是将数据复制到数据结构中,设置为False可以提高性能
indicator:显示合并数据中数据的来源情况
类似于关系型数据库的连接方式,可以根据一个或多个键将两张不同的DatFrame连接起来,由于默认how='inner'
,故合并表仅保留key重名的行,不重名的行将被丢弃。( 备注: merge()
只能完成两张表的连接,若有三个及以上表,需不断两两合并来实现)
该函数的典型应用场景: 两张表有相同内容的某一列(类似SQL中的主键),欲根据主键将两张表进行列拼接整合到一张表中,合并表的列数等于两个原数据表的列数和减去连接键的数量。
'on'
参数后传入多键列表即可。a. 两张表df1和df2的列名有重叠,且重叠列的内容完全相同,直接用pd.merge(df1, df2)
#样集1
df1=pd.DataFrame(np.arange(12).reshape(3,4),columns=['a','b','c','d'])
>>> df1
a b c d
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
#样集2
df2=pd.DataFrame({
'b':[1,5],'d':[3,7],'a':[0,4]})
>>> df2
b d a
0 1 3 0
1 5 7 4
#两张表df1和df2的列名有重叠,且重叠列的内容完全相同,直接用pd.merge(df1, df2)
pd.merge(df1,df2)
>>>
a b c d
0 0 1 2 3
1 4 5 6 7
b. 两张表df1和df2的列名有重叠,但重叠列的内容完全不同,须使用pd.merge(df1, df2, left_index=True, right_index=True, how='left')
(备注: 如果直接用pd.merge(df1, df2)
,将会得到一张空表,故必须指定行索引参数left_index
, right_index
,这种情况下最好使用join
实现。)
#样集1
df1=pd.DataFrame(np.arange(12).reshape(3,4),columns=['a','b','c','d'])
>>>df1
a b c d
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
#样集2
df2=pd.DataFrame({
'b':[15,6],'d':[1,11],'a':[0,6]})
>>>df2
b d a
0 15 1 0
1 6 11 6
#b. 两张表df1和df2的列名有重叠,但重叠列的内容完全不同
pd.merge(df1, df2, left_index=True, right_index=True, how='left')
>>>
a_x b_x c d_x b_y d_y a_y
0 0 1 2 3 15.0 1.0 0.0
1 4 5 6 7 6.0 11.0 6.0
2 8 9 10 11 NaN NaN NaN
DataFrame.join(other, on=None, how='left', lsuffix=' ', rsuffix=' ', sort=False)
参数的意义与merge
方法基本相同,只是join方法默认为左外连接how=’left’
该函数的典型应用场景:无重复列名的两个表df1和df2 基于行索引进行列拼接,直接使用df1.join(df2)
即可,无需添加任何参数,合并表的行数与left表相同,列数为left表+right表的列数之和,结果仅保留left表和right表中行索引相同的行,对列不做任何处理。如果两个表有重复的列名,需指定lsuffix
, rsuffix
参数。
利用join
也可 基于列索引进行列拼接,需借助参数‘on’
。常见的基于列索引的列拼接方式有3种:
(Ⅰ)列名不同,列内容有相同:需要用到 l.join(r.set_index(key of r), on='key of l')
(Ⅱ)列名和列内容均有相同:需要用到l.join(r.set_index(key), on='key')
(Ⅲ)列名不同,列内容也不同:这种情况是典型的基于行索引进行列拼接,不能用JOIN
的ON
参数。
JOIN 拼接列,主要用于基于行索引上的合并。
a. 无重复列名的两个表df1和df3基于 行索引,进行列拼接,直接使用df1.join(df2)
即可
b. 有重复列名的两个表df1和df2(即使内容没有重复)基于 行索引,进行列拼接,使用df1.join(df2)
时需要指定lsuffix
, rsuffix
参数,即:df1.join(df2, lsuffix='_l', rsuffix='_r')
,否则会报错。
#样集1
df1=pd.DataFrame(np.arange(12).reshape(3,4),columns=['a','b','c','d'])
>>>df1
a b c d
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
#样集2
df2=pd.DataFrame({
'b':[15,6],'d':[1,11],'a':[0,6]})
>>>df2
b d a
0 15 1 0
1 6 11 6
#用join合并表df1和表df2,需指定lsuffix, rsuffix参数,标识两个表的重复列名
df1.join(df2, lsuffix='_l', rsuffix='_r')
>>>
a_l b_l c d_l b_r d_r a_r
0 0 1 2 3 15.0 1.0 0.0
1 4 5 6 7 6.0 11.0 6.0
2 8 9 10 11 NaN NaN NaN
c. 列名不同,列内容有相同的两个表df1和df2基于 列索引,进行列拼接,使用l.join(r.set_index(key of r), on='key of l')
,这种JOIN的写法等同于前面提到的merge
设置left_on
,right_on
(备注:#列名不同,使用merge
进行列拼接时,内容相同的行可以作为键),因为merge
默认是内连接,所以返回的结果只有一行,而JOIN
返回的结果是以左表的key列为准,有两行。
#样集1
left=pd.DataFrame({
'key1':['foo','bar1'],'lval':[1,2]})
>>>left
key1 lval
0 foo 1
1 bar1 2
#样集2
right=pd.DataFrame({
'key2':['foo','bar'],'rval':[4,5]})
>>>right
key2 rval
0 foo 4
1 bar 5
#列名不同,列内容有相同的两个表df1和df2基于列索引,进行列拼接
left.join(right.set_index('key2'),on='key1') #.set_index()设置表right的列索引
>>>
key1 lval rval
0 foo 1 4.0
1 bar1 2 NaN
d. 列名和列内容均有相同的两个表df1和df2基于 列索引,进行列拼接,使用l.join(r.set_index(key), on='key')
,这种JOIN
的写法等同于前面提到的merge设置不带任何参数,而且这种情况下merge
会去掉重复的列
#样集1
left=pd.DataFrame({
'key':['foo','bar1'],'lval':[1,2]})
>>>
key lval
0 foo 1
1 bar1 2
#样集2
right=pd.DataFrame({
'key':['foo','bar'],'rval':[4,5]})
>>>
key rval
0 foo 4
1 bar 5
#列名和列内容均部分相同的表df1和df2进行基于列索引,列拼接
left.join(right.set_index('key'),on='key')
>>>
key lval rval
0 foo 1 4.0
1 bar1 2 NaN
#样集3
left=pd.DataFrame({
'key':['foo','bar1'],'val':[1,2]})
>>>
key val
0 foo 1
1 bar1 2
#样集4
right=pd.DataFrame({
'key':['foo','bar'],'val':[4,5]})
>>>
key val
0 foo 4
1 bar 5
#列名相同,列内容部分相同的表df1和df2基于列索引进行列合并,必须用参数lsuffix='_l',rsuffix='_r'指定重名列的下标,否则报错
left.join(right.set_index('key'),on='key',lsuffix='_l',rsuffix='_r')
>>>
key val_l val_r
0 foo 1 4.0
1 bar1 2 NaN
#特别注意,即使列名相同了,也必须用到' set_index(key)' 否则直接使用
left.join(right,on='key',lsuffix='_l',rsuffix='_r')
>>> ValueError: You are trying to merge on object and int64 columns. If you wish to proceed you should use pd.concat
#另外需明确,不指定'ON= '参数的情况下,JOIN是按行索引进行列拼接,不对列进行任何操作。
left.join(right,lsuffix='_l',rsuffix='_r')
>>>
key_l val_l key_r val_r
0 foo 1 foo 4
1 bar1 2 bar 5
DataFrame.append(other, ignore_index=False, verify_integrity=False, sort=None)
other: DataFrame or Series/dict-like object, or list of these
The data to append.
ignore_index : boolean, default False
If True, do not use the index labels.
verify_integrity : boolean, default False
If True, raise ValueError on creating index with duplicates.
sort: boolean, default None
只是join方法默认为左外连接how=’left’
append
是concat
的简略形式,只不过只能在axis=0
上进行合并
df1.append(df2),df1.append(df2,ignore_index=True)
DataFrame和Series进行合并的时候需要使用参数ignore_index=True
或者含有属性name,因为Series是只有一维索引的(备注:如果不添加参数ignore_index=True,那么会出错的。)。