【python資料分析(12)】Pandas實現對Excel列表資料整合(merge縱向合併、concat橫向連線)
在進行表格操作的時候,經常需要將兩個excel表格資料進行橫向合併,或者對原有的資料進行縱向擴充,這時候,就可以使用Pandas裡面的 merge
縱向合併和 concat
橫向連線功能了,如下:
2. 縱向合併
pd.merge
(left, right, how=‘inner’, on=None, left_on=None, right_on=None,left_index=False, right_index=False, sort=True, suffixes=(’x’, ‘y’), copy=True)
left
:第一個df right
:第二個df on
:參考鍵(left_on左邊df的參考鍵、right_on右邊df的參考鍵) left_index、right_index
how
:合併方式 sort
:排序引數 suffixes=('_x', '_y')
相同列標題時,主動新增字尾部分
樣本資料生成:
df1 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
df2 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
df3 = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
df4 = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
2.1 按照相同的列標題進行資料合併
print(df1)
print(df2)
print(pd.merge(df1, df2, on='key'))
–> 輸出的結果為:(最後的輸出結果是按住key欄位資料進行縱向合併)
key A B
0 K0 A0 B0
1 K1 A1 B1
2 K2 A2 B2
3 K3 A3 B3
key C D
0 K0 C0 D0
1 K1 C1 D1
2 K2 C2 D2
3 K3 C3 D3
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
2.2 按照多列標題進行資料合併
print(df3)
print(df4)
print(pd.merge(df3, df4, on=['key1','key2']))
–> 輸出的結果為:(按照兩列相同的資料為依據進行縱向資料合併,不同的行資料會被捨棄)
key1 key2 A B
0 K0 K0 A0 B0
1 K0 K1 A1 B1
2 K1 K0 A2 B2
3 K2 K1 A3 B3
key1 key2 C D
0 K0 K0 C0 D0
1 K1 K0 C1 D1
2 K1 K0 C2 D2
3 K2 K0 C3 D3
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
2.3 合併方式
根據前面的列出的引數可知引數 how:
1)合併方式預設是 inner
,也就是取交集的意思;
2)此外還有 outer
取並集,資料缺失範圍NaN;
3) how = 'left'
,按照左側的df(下面的df3)為參考合併,資料缺失範圍NaN
4) how = 'right'
,按照右側的df(下面的df4)為參考合併,資料缺失範圍NaN
print(pd.merge(df3, df4,on=['key1','key2'], how = 'inner'))
print(pd.merge(df3, df4, on=['key1','key2'], how = 'outer'))
print(pd.merge(df3, df4, on=['key1','key2'], how = 'left'))
print(pd.merge(df3, df4, on=['key1','key2'], how = 'right'))
–> 輸出的結果為:
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
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K0 K1 A1 B1 NaN NaN
2 K1 K0 A2 B2 C1 D1
3 K1 K0 A2 B2 C2 D2
4 K2 K1 A3 B3 NaN NaN
5 K2 K0 NaN NaN C3 D3
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K0 K1 A1 B1 NaN NaN
2 K1 K0 A2 B2 C1 D1
3 K1 K0 A2 B2 C2 D2
4 K2 K1 A3 B3 NaN NaN
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
3 K2 K0 NaN NaN C3 D3
2.4 按照行標題和索引標籤進行資料合併
left_on, right_on, left_index, right_index
→ 有時候合併的兩組的依據資料內容是一樣,但是標題(可以是行標題,也可以是索引標籤的name)不一樣時候,可以單獨設定左鍵與右鍵
1) 都是以行標題為鍵( left_on
、 right_on
)
df1 = pd.DataFrame({'lkey':list('bbacaab'),
'data1':range(7)})
df2 = pd.DataFrame({'rkey':list('abd'),
'date2':range(3)})
print(df1)
print(df2)
print(pd.merge(df1, df2, left_on='lkey', right_on='rkey'))
–> 輸出的結果為:(依據的鍵的內容也會在陣列列表中,可擴充套件)
lkey data1 0 b 0 1 b 1 2 a 2 3 c 3 4 a 4 5 a 5 6 b 6 rkey date2 0 a 0 1 b 1 2 d 2 lkey data1 rkey date2 0 b 0 b 1 1 b 1 b 1 2 b 6 b 1 3 a 2 a 0 4 a 4 a 0 5 a 5 a 0
2) 一個以行標題,一個以索引標籤( left_on
、 right_index
)
df1 = pd.DataFrame({'key':list('abcdfeg'), 'data1':range(7)}) df2 = pd.DataFrame({'date2':range(100,105)}, index = list('abcde')) print(df1) print(df2) print(pd.merge(df1, df2, left_on='key', right_index=True))
–> 輸出的結果為:(會選取相同的部分,不符合的會被捨棄)
key data1 0 a 0 1 b 1 2 c 2 3 d 3 4 f 4 5 e 5 6 g 6 date2 a 100 b 101 c 102 d 103 e 104 key data1 date2 0 a 0 100 1 b 1 101 2 c 2 102 3 d 3 103 5 e 5 104
所以left_on, right_on, left_index, right_index可以相互組合(四種搭配):
left_on + right_on
, left_on + right_index
, left_index + right_on
, left_index + right_index
3) sort
引數,這裡可以使用,但是建議使用 sort_values
, sort_index
,比較精細化
4) suffixes=('_x', '_y')
預設當資料的標題重名時候是以 _x
,和 _y
作為字尾的,可以進行修改
df1 = pd.DataFrame({'key':list('adcbfeg'), 'data1':[1,3,2,4,5,9,7]}) df2 = pd.DataFrame({'data1':range(100,105)}, index = list('abcde')) print(df1) print(df2) print(pd.merge(df1, df2, left_on='key', sort=True,suffixes=('_1', '_2'), right_index=True))
–> 輸出的結果為:
key data1 0 a 1 1 d 3 2 c 2 3 b 4 4 f 5 5 e 9 6 g 7 data1 a 100 b 101 c 102 d 103 e 104 key data1_1 data1_2 0 a 1 100 3 b 4 101 2 c 2 102 1 d 3 103 5 e 9 104
3. 橫向連線
pd.concat
(objs, axis=0, join=‘outer’, join_axes=None, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, copy=True)
括號內為預設引數
s1 = pd.Series([1,2,3]) s2 = pd.Series([2,3,4]) s3 = pd.Series([1,2,3],index = ['a','c','h']) s4 = pd.Series([2,3,4],index = ['b','e','d']) print(pd.concat([s1,s2])) print(pd.concat([s3,s4]).sort_index())
–> 輸出的結果為:
0 1 1 2 2 3 0 2 1 3 2 4 dtype: int64 a 1 b 2 c 2 d 4 e 3 h 3 dtype: int64
3.1 預設 axis=0
,行+行,當 axis=1
,列+列
print(pd.concat([s3,s4], axis=1))
–> 輸出的結果為:
0 1 a 1.0 NaN b NaN 2.0 c 2.0 NaN d NaN 4.0 e NaN 3.0 h 3.0 NaN
3.2 連線方式:join,join_axes
join
:{‘inner’,‘outer’},預設為“outer”。如何處理其他軸上的索引。outer為聯合和inner為交集。
join_axes
:指定聯合的index
s5 = pd.Series([1,2,3],index = ['a','b','c']) s6 = pd.Series([2,3,4],index = ['b','c','d']) print(pd.concat([s5,s6], axis= 1)) print(pd.concat([s5,s6], axis= 1, join='inner')) print(pd.concat([s5,s6], axis= 1, join_axes=[['a','b','d']]))
–> 輸出的結果為:
0 1 a 1.0 NaN b 2.0 2.0 c 3.0 3.0 d NaN 4.0 0 1 b 2 2 c 3 3 0 1 a 1.0 NaN b 2.0 2.0 d NaN 4.0
3.3 多層次索引標籤(覆蓋列名)
1) keys
:序列,預設值無。使用傳遞的鍵作為最外層構建層次索引
sre = pd.concat([s5,s6], keys = ['one','two']) print(sre,type(sre)) print(sre.index)
–> 輸出的結果為:
one a 1 b 2 c 3 two b 2 c 3 d 4 dtype: int64 <class 'pandas.core.series.Series'> MultiIndex([('one', 'a'), ('one', 'b'), ('one', 'c'), ('two', 'b'), ('two', 'c'), ('two', 'd')], )
2) axis = 1
, 覆蓋列名(相當於指定新的列標題)
sre = pd.concat([s5,s6], axis=1, keys = ['one','two']) print(sre,type(sre))
–> 輸出的結果為:
one two a 1.0 NaN b 2.0 2.0 c 3.0 3.0 d NaN 4.0 <class 'pandas.core.frame.DataFrame'>
★★★★★ 3.4 資料修補
1) pd.combine_first()
進行資料的修補, 是將括號裡面的資料df2補充到前面的資料df1中
df1 = pd.DataFrame([[np.nan, 3., 5.], [-4.6, np.nan, np.nan],[np.nan, 7., np.nan]]) df2 = pd.DataFrame([[-42.6, np.nan, -8.2], [-5., 1.6, 4]],index=[1, 2]) print(df1) print(df2) print(df1.combine_first(df2))
–> 輸出的結果為:
0 1 2 0 NaN 3.0 5.0 1 -4.6 NaN NaN 2 NaN 7.0 NaN 0 1 2 1 -42.6 NaN -8.2 2 -5.0 1.6 4.0 0 1 2 0 NaN 3.0 5.0 1 -4.6 NaN -8.2 2 -5.0 7.0 4.0
2) update()
直接df2覆蓋df1,相同index位置,更新df1中的資料
df1.update(df2) print(df1)
–> 輸出的結果為:(注意對比和上面的結果)
0 1 2 0 NaN 3.0 5.0 1 -42.6 NaN -8.2 2 -5.0 1.6 4.0