Fork me on GitHub

一文搞定Pandas数据合并

一文搞定pandas的数据合并

在实际处理数据业务需求中,我们经常会遇到这样的需求:将多个表连接起来再进行数据的处理和分析,类似SQL中的连接查询功能

pandas中也提供了几种方法来实现这个功能,表现最突出、使用最为广泛的方法是merge。本文中将下面👇四种方法及参数通过实际案例来进行具体讲解。

  • merge
  • append
  • join
  • concat

文章目录

导入库

做数据分析的时候这两个库是必须导入的,国际惯例一般。

1
2
import pandas as pd
import numpy as np

merge

官方参数

官方提供的merge函数的参数如下:

下面将通过案例讲解几个重要参数的使用方法:

1
2
3
4
5
6
DataFrame.merge(left, right,
how='inner', # {‘left’, ‘right’, ‘outer’, ‘inner’}, default ‘inner’
on=None,
left_on=None, right_on=None,
sort=False,
suffixes=('_x', '_y'))

模拟数据

注意4组数据的不同

1
2
3
4
5
# 生成3个DataFrame型的数据

df1 = pd.DataFrame({'key':['a','b','b'], # a---b---b
'data1': range(3)})
df1
key data1
0 a 0
1 b 1
2 b 2
1
2
3
df2 = pd.DataFrame({'key':['a','b','c'],   # a---b---c
'data2': range(3,6)})
df2
key data2
0 a 3
1 b 4
2 c 5
1
2
3
df3 = pd.DataFrame({'key':['b','c','d'],   # b---c---d
'data3': range(6,9)})
df3
key data3
0 b 6
1 c 7
2 d 8
1
2
3
df4 = pd.DataFrame({'key':['a','b','c'],   # a---b---c
'data4': range(9,12)})
df4
key data4
0 a 9
1 b 10
2 c 11

使用默认参数

1
2
3
# 合并df1和df2

pd.merge(df1, df2)
key data1 data2
0 a 0 3
1 b 1 4
2 b 2 4
1
2
3
# 效果同上

df1.merge(df2)
key data1 data2
0 a 0 3
1 b 1 4
2 b 2 4

参数how

how参数的取值有4种:

  • inner(默认)
  • outer
  • right
  • left
1
2
3
# 1-默认使用inner:通过key的交集取值

pd.merge(df1,df2)
key data1 data2
0 a 0 3
1 b 1 4
2 b 2 4
1
pd.merge(df1,df2,how='inner')
key data1 data2
0 a 0 3
1 b 1 4
2 b 2 4
1
2
3
# 2-outer: 保留两个数据框的全部数据,不存在的则用NaN

pd.merge(df1,df2,how='outer')
key data1 data2
0 a 0.0 3
1 b 1.0 4
2 b 2.0 4
3 c NaN 5
1
df1
key data1
0 a 0
1 b 1
2 b 2
1
df2
key data2
0 a 3
1 b 4
2 c 5

1
2
3
# 3- left: 保留左边的全部数据

pd.merge(df1, df3, how='left')
key data1 data3
0 a 0 NaN
1 b 1 6.0
2 b 2 6.0
1
2
3
# 左表df1

df1
key data1
0 a 0
1 b 1
2 b 2
1
df3
key data3
0 b 6
1 c 7
2 d 8
1
2
3
# 4-right:保留右表的全部数据

pd.merge(df1, df3, how='right')
key data1 data3
0 b 1.0 6
1 b 2.0 6
2 c NaN 7
3 d NaN 8

1
2
3
# 右表df3

df3
key data3
0 b 6
1 c 7
2 d 8
1
df1
key data1
0 a 0
1 b 1
2 b 2

参数on

用于连接的列索引列名,必须同时存在于左右的两个dataframe型数据中,类似SQL中两个表的相同字段属性

如果没有指定或者其他参数也没有指定,则以两个dataframe型数据的相同键作为连接键

on参数为单个字段
1
2
# pd.merge(df1,df2)
pd.merge(df1,df2,on='key') # key同时存在
key data1 data2
0 a 0 3
1 b 1 4
2 b 2 4
1
df1
key data1
0 a 0
1 b 1
2 b 2
1
df2
key data2
0 a 3
1 b 4
2 c 5
1
2
3
4
5
6
# 另一个例子

left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
left
key A B
0 K0 A0 B0
1 K1 A1 B1
2 K2 A2 B2
3 K3 A3 B3
1
2
3
4
right = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
right
key C D
0 K0 C0 D0
1 K1 C1 D1
2 K2 C2 D2
3 K3 C3 D3
1
2
3
4
5
# on参数传递的key作为连接键-类似SQL中两个表的关联字段
# 这个键在两个DataFrame必须是完全相同的

result = pd.merge(left, right, on='key')
result
key A B C D
0 K0 A0 B0 C0 D0
1 K1 A1 B1 C1 D1
2 K2 A2 B2 C2 D2
3 K3 A3 B3 C3 D3
on参数为多个字段-列表形式
1
2
3
4
5
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
left
key1 key2 A B
0 K0 K0 A0 B0
1 K0 K1 A1 B1
2 K1 K0 A2 B2
3 K2 K1 A3 B3
1
2
3
4
5
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
right
key1 key2 C D
0 K0 K0 C0 D0
1 K1 K0 C1 D1
2 K1 K0 C2 D2
3 K2 K0 C3 D3
1
2
3
4
5
# on参数为列表形式
# [K1,K0]出现两次

result = pd.merge(left, right, on=['key1', 'key2'])
result
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K0 A2 B2 C1 D1
2 K1 K0 A2 B2 C2 D2

参数left_on/right_on

1
2
3
df7 = pd.DataFrame({'l_key':['b','c','d'],
'data7': range(6,9)})
df7
l_key data7
0 b 6
1 c 7
2 d 8
1
2
3
df8 = pd.DataFrame({'r_key':['b','c','d'],    # 某两个键的名字不同,但是取值相同
'data8': range(9,12)})
df8
r_key data8
0 b 9
1 c 10
2 d 11
1
pd.merge(df7,df8,left_on='l_key',right_on='r_key')
l_key data7 r_key data8
0 b 6 b 9
1 c 7 c 10
2 d 8 d 11

参数suffixes

合并的时候一列两个表同名,但是取值不同,如果都想要保存下来,就使用加后缀的方法,默认是_x,_y

1
2
3
df9 = pd.DataFrame({'key':['b','c','d'],
'data': range(5,8)})
df9
key data
0 b 5
1 c 6
2 d 7
1
2
3
df10 = pd.DataFrame({'key':['b','c','d'],
'data': [9,5,10]})
df10
key data
0 b 9
1 c 5
2 d 10
1
pd.merge(df9,df10,on='key',suffixes=['_left','_right'])   # 自定义后缀
key data_left data_right
0 b 5 9
1 c 6 5
2 d 7 10
1
pd.merge(df9,df10,on='key',suffixes=['_x','_y'])   # 官方默认后缀_x,_y
key data_x data_y
0 b 5 9
1 c 6 5
2 d 7 10

参数sort

对连接的时候相同键的取值进行排序

1
2
3
4
df9 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'key': ['K0', 'K1', 'K0', 'K1']})
df9
A B key
0 A0 B0 K0
1 A1 B1 K1
2 A2 B2 K0
3 A3 B3 K1
1
2
3
4
df10 = pd.DataFrame({'C': ['C0', 'C1'],
'D': ['D0', 'D1']},
index=['K0', 'K1'])
df10
C D
K0 C0 D0
K1 C1 D1
1
pd.merge(df9, df10, left_on='key', right_index=True, how='left', sort=False)
A B key C D
0 A0 B0 K0 C0 D0
1 A1 B1 K1 C1 D1
2 A2 B2 K0 C0 D0
3 A3 B3 K1 C1 D1
1
2
3
#  对连接的键(key)的取值进行排序

pd.merge(df9, df10, left_on='key', right_index=True, how='left', sort=True)
A B key C D
0 A0 B0 K0 C0 D0
2 A2 B2 K0 C0 D0
1 A1 B1 K1 C1 D1
3 A3 B3 K1 C1 D1

concat

官方参数

concat方法是将两个DataFrame数据框中的数据进行合并

  • 通过axis参数指定是在行还是列方向上合并
  • 参数ignore_index实现合并后的索引重排

生成数据

1
2
data1 = pd.DataFrame({'key1': ['math','chinese','english'], 'value': [87,92,83]})
data1
key1 value
0 math 87
1 chinese 92
2 english 83
1
2
data2 = pd.DataFrame({'key1': ['math','chinese','english'],  'value': [97,82,76]})
data2
key1 value
0 math 97
1 chinese 82
2 english 76

指定合并轴

1
pd.concat([data1, data2])  # 合并方向默认是axis=0,行方向上合并
key1 value
0 math 87
1 chinese 92
2 english 83
0 math 97
1 chinese 82
2 english 76
1
pd.concat([data1, data2],axis=1)    # 改成axis=1,列方向上合并
key1 value key1 value
0 math 87 math 97
1 chinese 92 chinese 82
2 english 83 english 76

改变索引

1
pd.concat([data1, data2], ignore_index=True)
key1 value
0 math 87
1 chinese 92
2 english 83
3 math 97
4 chinese 82
5 english 76
1
pd.concat([data1, data2])
key1 value
0 math 87
1 chinese 92
2 english 83
0 math 97
1 chinese 82
2 english 76

join参数

1
2
3
4
data3 = pd.DataFrame({'key3': ['math','chinese','english'],
'value': [95, 88, 89]})

data3
key3 value
0 math 95
1 chinese 88
2 english 89
1
2
3
4
data4 = pd.DataFrame({'key4': ['math','chinese','english'],
'value': [90, 83, 94]})

data4
key4 value
0 math 90
1 chinese 83
2 english 94
1
pd.concat([data3, data4])
key3 key4 value
0 math NaN 95
1 chinese NaN 88
2 english NaN 89
0 NaN math 90
1 NaN chinese 83
2 NaN english 94
1
pd.concat([data3, data4], join='outer')   # 字段如果不存在,则用NaN代
key3 key4 value
0 math NaN 95
1 chinese NaN 88
2 english NaN 89
0 NaN math 90
1 NaN chinese 83
2 NaN english 94
1
pd.concat([data3, data4], join='inner')   # 只合并相同的字段属性
value
0 95
1 88
2 89
0 90
1 83
2 94

sort-属性排序

1
pd.concat([data3, data4], sort=False)
key3 value key4
0 math 95 NaN
1 chinese 88 NaN
2 english 89 NaN
0 NaN 90 math
1 NaN 83 chinese
2 NaN 94 english
1
2
3
# 默认排序

pd.concat([data3, data4])
key3 key4 value
0 math NaN 95
1 chinese NaN 88
2 english NaN 89
0 NaN math 90
1 NaN chinese 83
2 NaN english 94

append

官方参数

基本使用

1
data3.append(data4)   # 等同下面的语句中concat写法
key3 key4 value
0 math NaN 95
1 chinese NaN 88
2 english NaN 89
0 NaN math 90
1 NaN chinese 83
2 NaN english 94
1
pd.concat([data3, data4])
key3 key4 value
0 math NaN 95
1 chinese NaN 88
2 english NaN 89
0 NaN math 90
1 NaN chinese 83
2 NaN english 94

改变索引-自然数排序

1
data3.append(data4, ignore_index=True)  # 设置参数
key3 key4 value
0 math NaN 95
1 chinese NaN 88
2 english NaN 89
3 NaN math 90
4 NaN chinese 83
5 NaN english 94
1
data3.append(data4)
key3 key4 value
0 math NaN 95
1 chinese NaN 88
2 english NaN 89
0 NaN math 90
1 NaN chinese 83
2 NaN english 94

sort=True-属性的排序

1
data3.append(data4)   # 默认对字段属性排序
key3 key4 value
0 math NaN 95
1 chinese NaN 88
2 english NaN 89
0 NaN math 90
1 NaN chinese 83
2 NaN english 94
1
data3.append(data4, sort=False)
key3 value key4
0 math 95 NaN
1 chinese 88 NaN
2 english 89 NaN
0 NaN 90 math
1 NaN 83 chinese
2 NaN 94 english
1
2


join

官方参数

通过相同索引合并

1
2
3
4
data5 = pd.DataFrame({'A': [81,97,88],'B': [93,88,78]},
index=['K0','K1','K2'])

data5
A B
K0 81 93
K1 97 88
K2 88 78
1
2
3
4
data6 = pd.DataFrame({'C': [95,77,80],'D': [80,98,84]},
index=['K0','K1','K2'])

data6
C D
K0 95 80
K1 77 98
K2 80 84
1
data5.join(data6)  # 同下效果
A B C D
K0 81 93 95 80
K1 97 88 77 98
K2 88 78 80 84
1
pd.concat([data5, data6],axis=1)  # 指定沿着axis=1
A B C D
K0 81 93 95 80
K1 97 88 77 98
K2 88 78 80 84
1
2
3
data7 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3', 'K4', 'K5'],
'A': ['A0', 'A1', 'A2', 'A3', 'A4', 'A5']})
data7
key A
0 K0 A0
1 K1 A1
2 K2 A2
3 K3 A3
4 K4 A4
5 K5 A5
1
2
3
data8 = pd.DataFrame({'key': ['K0', 'K1', 'K2'],
'B': ['B0', 'B1', 'B2']})
data8
key B
0 K0 B0
1 K1 B1
2 K2 B2

相同字段属性指后缀

1
data7.join(data8,lsuffix='_left', rsuffix='_right')  # 存在相同的字段,指定新生成的字段后缀
key_left A key_right B
0 K0 A0 K0 B0
1 K1 A1 K1 B1
2 K2 A2 K2 B2
3 K3 A3 NaN NaN
4 K4 A4 NaN NaN
5 K5 A5 NaN NaN

相同字段变成索引index

1
data7.set_index('key').join(data8.set_index('key'))
A B
key
K0 A0 B0
K1 A1 B1
K2 A2 B2
K3 A3 NaN
K4 A4 NaN
K5 A5 NaN

相同字段保留一次

1
data7.join(data8.set_index('key'), on='key')
key A B
0 K0 A0 B0
1 K1 A1 B1
2 K2 A2 B2
3 K3 A3 NaN
4 K4 A4 NaN
5 K5 A5 NaN
1
data7.join(data8.set_index('key'), on='key').set_index('key')   # 和上一种方法的转换效果相同,最后在使用一次set_index()
A B
key
K0 A0 B0
K1 A1 B1
K2 A2 B2
K3 A3 NaN
K4 A4 NaN
K5 A5 NaN

本文标题:一文搞定Pandas数据合并

发布时间:2020年09月13日 - 10:09

原始链接:http://www.renpeter.cn/2020/09/13/%E4%B8%80%E6%96%87%E6%90%9E%E5%AE%9APandas%E6%95%B0%E6%8D%AE%E5%90%88%E5%B9%B6.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Coffee or Tea