Python学习笔记:数据合并join、merge、concat、append、combine、combine_first等

一、对比总结

简单总结,通过 mergejoin 合并的数据后数据的列变多,通过 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 joinright joininner 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

参考链接:Pandas中合并数据的5个函数,各有千秋!

参考链接:python 数据合并函数merge( )

参考链接:【python】详解pandas库的pd.merge函数

参考链接:python 合并(merge , concat , join , combine_first)

参考链接:python pandas 合并数据函数merge join concat combine_first 区分

参考链接:pandas.DataFrame.combine_first

参考链接:pandas 之 combine 详解,如果 df 不存在、other 中存在,会如何处理

参考链接:Pandas玩转数据(五) -- Concatenate和Combine

posted @ 2021-09-15 14:34  Hider1214  阅读(5336)  评论(0编辑  收藏  举报