一、對比總結
簡單總結,通過 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