Python学习笔记:数据合并join、merge、concat、append、combine、combine_first等
一、对比总结
简单总结,通过 merge
和 join
合并的数据后数据的列变多,通过 concat
合并后的数据行列都可以变多(axis=1),而 combine_first
可以用一个数据填充另一个数据的缺失数据。
函数 | 说明 |
---|---|
join | 主要用于基于索引的横向合并拼接 |
merge | 主要用于基于指定列的横向合并拼接(类似SQL的inner join等) |
concat | 可用于横向和纵向合并拼接 |
append | 主要用于纵向追加 |
combine | 将2个DataFrame按列进行组合 |
combine_first | 为数据打补丁 |
二、join
join
是基于索引的横向拼接,如果索引一致,直接横向拼接。
如果索引不一致,则会用 Nan
值填充。
# 索引一致
import pandas as pd
x = pd.DataFrame({'A':['x1','x2','x3'],
'B':['y1','y2','y3']}, index=[0,1,2])
y = pd.DataFrame({'C':['z1','z2','z3'],
'D':['m1','m2','m3']}, index=[0,1,2])
x.join(y)
'''
A B C D
0 x1 y1 z1 m1
1 x2 y2 z2 m2
2 x3 y3 z3 m3
'''
# 索引不一致
import pandas as pd
x = pd.DataFrame({'A':['x1','x2','x3'],
'B':['y1','y2','y3']}, index=[0,1,2])
y = pd.DataFrame({'C':['z1','z2','z3'],
'D':['m1','m2','m3']}, index=[1,2,3])
x.join(y)
'''
A B C D
0 x1 y1 NaN NaN
1 x2 y2 z1 m1
2 x3 y3 z2 m2
'''
# 合并的列名相同 指定 lsuffix、rsuffix 进行区分
import pandas as pd
x = pd.DataFrame({'A':['x1','x2','x3'],
'B':['y1','y2','y3']}, index=[0,1,2])
y = pd.DataFrame({'B':['z1','z2','z3'],
'D':['m1','m2','m3']}, index=[0,1,2])
x.join(y, lsuffix='_xx', rsuffix='_yy')
'''
A B_xx B_yy D
0 x1 y1 z1 m1
1 x2 y2 z2 m2
2 x3 y3 z3 m3
'''
三、merge
merge
是基于指定列的横向拼接,类似于数据库的 left join
、right join
、inner join
等连接方式,可以根据一个或多个键将不同的 DataFrame
连接起来。
该函数的典型应用场景是,针对同一个主键存在两张不同字段的表,根据主键整合到一张表里面。
可以指定不同的how参数,表示连接方式。
- inner 内连
- left 左连
- right 右连
- outer 全连,默认为 inner
需要注意的是使用 merge
合并时,两个数据集的合并条件类型须一致。
1.使用语法
pd.merge(left_data, right_data, 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)
2.参数
- left: 拼接的左侧DataFrame对象
- right: 拼接的右侧DataFrame对象
- on: 要加入的列或索引级别名称。 必须在左侧和右侧DataFrame对象中找到。 如果未传递且left_index和right_index为False,则DataFrame中的列的交集将被推断为连接键。
- left_on:左侧DataFrame中的列或索引级别用作键。 可以是列名,索引级名称,也可以是长度等于DataFrame长度的数组。
- right_on: 左侧DataFrame中的列或索引级别用作键。 可以是列名,索引级名称,也可以是长度等于DataFrame长度的数组。
- left_index: 如果为True,则使用左侧DataFrame中的索引(行标签)作为其连接键。 对于具有MultiIndex(分层)的DataFrame,级别数必须与右侧DataFrame中的连接键数相匹配。
- right_index: 与left_index功能相似。
- how::取值为‘left’, ‘right’, ‘outer’, ‘inner’。 默认inner。inner是取交集,outer取并集,没出现的会将缺失的部分添加缺失值。
- sort: 按字典顺序通过连接键对结果DataFrame进行排序。 默认为False,设置为False将在很多情况下显着提高性能。
- suffixes: 用于重叠列的字符串后缀元组。 默认为(‘_x’,’ _y’)。
- copy:始终从传递的DataFrame对象复制数据(默认为True),即使不需要重建索引也是如此。
- indicator:将一列添加到名为_merge的输出DataFrame,其中包含有关每行源的信息。 _merge 是分类类型,并且对于其合并键仅出现在“左”DataFrame中的观察值,取得值为left_only,对于其合并键仅出现在“右”DataFrame中的观察值为right_only,并且如果在两者中都找到观察点的合并键,则为both。
3.实操
- 左右连接键名一致
# 创建测试表
import pandas as pd
df1=pd.DataFrame({'key':['a','b','a','b','b'],'value1':range(5)})
df2=pd.DataFrame({'key':['a','c','c','c','c'],'value2':range(5)})
# 左右连接键名一致
# 以df1、df2中相同的列名key进行连接,默认how='inner', 等同于 pd.merge(df1,df2,on='key',how='inner')
pd.merge(df1, df2)
'''
key value1 value2
0 a 0 0
1 a 2 0
'''
# 左连接 没有值则用NaN填充
pd.merge(df1, df2, how='left') # 左
pd.merge(df1, df2, how='right') # 右
'''
key value1 value2
0 a 0 0.0
1 b 1 NaN
2 a 2 0.0
3 b 3 NaN
4 b 4 NaN
'''
# 全连接 取并集 没有值则用NaN填充
pd.merge(df1, df2, how='outer')
'''
key value1 value2
0 a 0.0 0.0
1 a 2.0 0.0
2 b 1.0 NaN
3 b 3.0 NaN
4 b 4.0 NaN
5 c NaN 1.0
6 c NaN 2.0
7 c NaN 3.0
8 c NaN 4.0
'''
- 左右连接键名不一致 可以使用left_on、right_on进行指定
# 左右连接键名不一致 可以使用left_on、right_on进行指定
df3=pd.DataFrame({'lkey':['a','b','a','b','b'],'data1':range(5)})
df4=pd.DataFrame({'rkey':['a','c','c','c','c'],'data2':range(5)})
# 连接
pd.merge(df3, df4, left_on='lkey', right_on='rkey') # 内连接 默认 how='inner'
pd.merge(df3, df4, left_on='lkey', right_on='rkey', how='outer') # 全连接
pd.merge(df3, df4, left_on='lkey', right_on='rkey', how='left') # 左连接
pd.merge(df3, df4, left_on='lkey', right_on='rkey', how='right') # 右连接
- 索引作为连接键
import numpy as np
df5=pd.DataFrame(np.arange(12).reshape(3,4),index=list('abc'),columns=['v1','v2','v3','v4'])
df6=pd.DataFrame(np.arange(12,24,1).reshape(3,4),index=list('abd'),columns=['v5','v6','v7','v8'])
pd.merge(df5, df6, left_index=True, right_index=True)
pd.merge(df5, df6, left_index=True, right_index=True, how='outer')
- 传入on的参数为列表(多个连接键)
df7 = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
df8 = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
# 多键连接
pd.merge(df7, df8, on=['key1', 'key2'])
- 列名相同添加后缀
df9=pd.DataFrame({'key':['a','b','a','b','b'],'data':range(5)})
df10=pd.DataFrame({'key':['a','c','c','c','c'],'data':range(5)})
pd.merge(df9, df10, on='key')
'''
key data_x data_y
0 a 0 0
1 a 2 0
'''
pd.merge(df9, df10, on='key', suffixes=('_123', '_456'))
'''
key data_123 data_456
0 a 0 0
1 a 2 0
'''
- 传入 indicator 参数
# 添加一列 显示数据关联使用情况
pd.merge(df1, df2, indicator=True, how='outer')
'''
key value1 value2 _merge
0 a 0.0 0.0 both
1 a 2.0 0.0 both
2 b 1.0 NaN left_only
3 b 3.0 NaN left_only
4 b 4.0 NaN left_only
5 c NaN 1.0 right_only
6 c NaN 2.0 right_only
7 c NaN 3.0 right_only
8 c NaN 4.0 right_only
'''
# 指标参数也接受字符串参数 作为指标列名称
pd.merge(df1, df2, indicator='is_used', how='outer')
'''
key value1 value2 is_used
0 a 0.0 0.0 both
1 a 2.0 0.0 both
2 b 1.0 NaN left_only
'''
- sort 对连接键进行排序
pd.merge(df3, df4, how='outer', sort=True)
merge
的应用场景是针对连接键来进行操作的,连接键可以是 index
或者 column
。
但是实际应用时一定注意的是 left
或者 right
的键值不要重复,避免麻烦。
- 多数据框合并
# 一个一个拼接
pf.merge(pd.merge(df1, df2, how='left'), df3, how='left')
四、concat
concat
函数既可以用于横向拼接,也可以用于纵向拼接。
# 默认纵向拼接
# 列名相同直接拼接 列名不同 不存在的值为NaN
import pandas as pd
df1=pd.DataFrame({'key':['a','b','a','b','b'],'value1':range(5)})
df2=pd.DataFrame({'key':['a','c','c','c','c'],'value2':range(5)})
pd.concat([df1, df2], axis=1) # 横向
pd.concat([df1, df2], axis=0) # 纵向
# ignore_index 忽略原来的索引 自动生成新索引
pd.concat([df1, df2], axis=0, ignore_index=True)
# 多数据集合并
pd.concat([df1, df2, df3, ...])
# 利用keys生成多重索引 判断数据来源
pd.concat([df1, df2, df3], keys=[1,2,3])
五、append
append
主要用于纵向追加数据。
import pandas as pd
df1=pd.DataFrame({'key':['a','b','a','b','b'],'value1':range(5)})
df2=pd.DataFrame({'key':['a','c','c','c','c'],'value2':range(5)})
df1.append(df2)
# 重建索引
df1.append(df2, ignore_index=True)
df1.append(df2).reset_index(drop=True) # 同上
六、combine
conbine
可以通过使用函数,把两个 DataFrame
按列进行组合对比。
注意:按列进行对比,而不是按行、按值等。
1.使用语法
df1.combine(df2, func, fill_value=None, overwrite=True)
2.实操
# 返回最小的那一列
import pandas as pd
df1 = pd.DataFrame({'A': [0, 0], 'B': [4, 4]})
df2 = pd.DataFrame({'A': [1, 1], 'B': [3, 3]})
# 整列比较
take_smaller = lambda x, y: x if x.sum() < y.sum() else y
df1.combine(df2, take_smaller)
'''
A B
0 0 3
1 0 3
'''
# 对应位置的最小值
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'A': [5, 0], 'B': [2, 4]})
df2 = pd.DataFrame({'A': [1, 1], 'B': [3, 3]})
df1.combine(df2, np.minimum)
'''
A B
0 1 2
1 0 3
'''
# 填充缺失值
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'A': [0, 0], 'B': [None, 4]})
df2 = pd.DataFrame({'A': [1, 1], 'B': [3, 3]})
df1.combine(df2, take_smaller, fill_value=-5)
'''
A B
0 0 -5.0
1 0 4.0
'''
对于 DataFrame
中不存在的列,结果为 NaN
。
# 参数 overwrite 默认为 True
# 当 df 中存在、other 中不存在时,可以通过该参数确定是否使用 other 的值填充 df
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'A': [1, 1], 'B': [4, 4]})
df2 = pd.DataFrame({'B': [3, 3], 'C': [1, 1], }, index=[1, 2])
df1.combine(df2, take_smaller, overwrite=False)
'''
A B C
0 1.0 NaN NaN
1 1.0 3.0 NaN
2 NaN 3.0 NaN
'''
返回最大值
import pandas as pd
import numpy as np
x = pd.DataFrame({"A":[3,4],"B":[1,4]})
y = pd.DataFrame({"A":[1,2],"B":[5,6]})
x.combine(y, lambda a, b: np.where(a > b, a, b))
'''
A B
0 3 5
1 4 6
'''
返回对应位置上的最大值
# numpy.where 用法
numpy.where(condition, x, y)
# 满足条件(condition),输出x,不满足输出y
七、combine_first
实例方法 combine_first
,它既不是行之间的连接,也不是列之间的连接。
它为数据“打补丁”:用参数对象中的数据为调用者对象的缺失数据“打补丁”。
import pandas as pd
import numpy as np
x = pd.DataFrame([[np.nan, 3., 5.], [-4.6, np.nan, np.nan],[np.nan, 7., np.nan]])
y = pd.DataFrame([[-42.6, np.nan, -8.2], [-5., 1.6, 4]], index=[1, 2])
# 如果x数据缺失,则用y数据填充
x.combine_first(y)
'''
0 1 2
0 NaN 3.0 5.0
1 -4.6 NaN -8.2
2 -5.0 7.0 4.0
'''
# 不存在的列直接用NaN替代
df1 = pd.DataFrame({'A': [None, 0], 'B': [4, None]})
df2 = pd.DataFrame({'B': [3, 3], 'C': [1, 1]}, index=[1, 2])
df1.combine_first(df2)
'''
A B C
0 NaN 4.0 NaN
1 0.0 3.0 1.0
2 NaN 3.0 1.0
'''
八、np.concatenate
类似于 pd.concat
函数。
import pandas as pd
import numpy as np
from pandas import Series, DataFrame
arr1 = np.arange(9).reshape(3,3)
arr2 = np.arange(9).reshape(3,3)
# 默认 axis=0 纵向结合
np.concatenate([arr1, arr2])
'''
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
'''
# 横向结合
np.concatenate([arr1, arr2], axis=1)
s1 = Series([1,2,3], index=['X','Y','Z'])
s2 = Series([4,5], index=['A','B'])
pd.concat([s1, s2])
pd.concat([s1, s2], axis=1) # 缺失值会补齐为NaN
参考链接:【python】详解pandas库的pd.merge函数
参考链接:python 合并(merge , concat , join , combine_first)
参考链接:python pandas 合并数据函数merge join concat combine_first 区分
参考链接:pandas.DataFrame.combine_first