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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM