1. 程式人生 > 其它 >【python資料分析(12)】Pandas實現對Excel列表資料整合(merge縱向合併、concat橫向連線)

【python資料分析(12)】Pandas實現對Excel列表資料整合(merge縱向合併、concat橫向連線)

1. 背景

在進行表格操作的時候,經常需要將兩個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_onright_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_onright_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_valuessort_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