1. 程式人生 > >python merge、concat合併資料集

python merge、concat合併資料集

資料規整化:合併、清理、過濾

pandas和python標準庫提供了一整套高階、靈活的、高效的核心函式和演算法將資料規整化為你想要的形式!

本篇部落格主要介紹:

合併資料集:.merge()、.concat()等方法,類似於SQL或其他關係型資料庫的連線操作。

合併資料集

1) merge 函式引數

引數 說明
left 參與合併的左側DataFrame
right 參與合併的右側DataFrame
how 連線方式:‘inner’(預設);還有,‘outer’、‘left’、‘right’
on 用於連線的列名,必須同時存在於左右兩個DataFrame物件中,如果位指定,則以left和right列名的交集作為連線鍵
left_on 左側DataFarme中用作連線鍵的列
right_on 右側DataFarme中用作連線鍵的列
left_index 將左側的行索引用作其連線鍵
right_index 將右側的行索引用作其連線鍵
sort 根據連線鍵對合並後的資料進行排序,預設為True。有時在處理大資料集時,禁用該選項可獲得更好的效能
suffixes 字串值元組,用於追加到重疊列名的末尾,預設為(‘_x’,‘_y’).例如,左右兩個DataFrame物件都有‘data’,則結果中就會出現‘data_x’,‘data_y’
copy 設定為False,可以在某些特殊情況下避免將資料複製到結果資料結構中。預設總是賦值

1、多對一的合併(一個表的連線鍵列有重複值,另一個表中的連線鍵沒有重複值)

import pandas as pd
import numpy as np

df1 = pd.DataFrame({'key':['b','b','a','c','a','a','b'],'data1': range(7)})

df1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
data1 key
0 0 b
1 1 b
2 2 a
3 3 c
4 4 a
5 5 a
6 6 b
df2 = pd.DataFrame({'key':['a','b','d'],'data2':range(3)})

df2
  • 1
  • 2
  • 3
data2 key
0 0 a
1 1 b
2 2 d
pd.merge(df1,df2)#預設情況
  • 1
data1 key data2
0 0 b 1
1 1 b 1
2 6 b 1
3 2 a 0
4 4 a 0
5 5 a 0
df1.merge(df2)
  • 1
data1 key data2
0 0 b 1
1 1 b 1
2 6 b 1
3 2 a 0
4 4 a 0
5 5 a 0
df1.merge(df2,on = 'key',how = 'inner')#內連線,取交集
  • 1
data1 key data2
0 0 b 1
1 1 b 1
2 6 b 1
3 2 a 0
4 4 a 0
5 5 a 0
df1.merge(df2,on = 'key',how = 'outer')#外連結,取並集,並用nan填充
  • 1
data1 key data2
0 0.0 b 1.0
1 1.0 b 1.0
2 6.0 b 1.0
3 2.0 a 0.0
4 4.0 a 0.0
5 5.0 a 0.0
6 3.0 c NaN
7 NaN d 2.0
df1.merge(df2,on = 'key',how = 'left')#左連線,左側DataFrame取全部,右側DataFrame取部分
  • 1
data1 key data2
0 0 b 1.0
1 1 b 1.0
2 2 a 0.0
3 3 c NaN
4 4 a 0.0
5 5 a 0.0
6 6 b 1.0
df1.merge(df2,on = 'key',how = 'right')#右連線,右側DataFrame取全部,左側DataFrame取部分
  • 1
data1 key data2
0 0.0 b 1
1 1.0 b 1
2 6.0 b 1
3 2.0 a 0
4 4.0 a 0
5 5.0 a 0
6 NaN d 2

如果左右側DataFrame的連線鍵列名不一致,但是取值有重疊,可使用left_on、right_on來指定左右連線鍵

df3 = pd.DataFrame({'lkey':['b','b','a','c','a','a','b'],'data1': range(7)})

df3
  • 1
  • 2
  • 3
data1 lkey
0 0 b
1 1 b
2 2 a
3 3 c
4 4 a
5 5 a
6 6 b
df4 = pd.DataFrame({'rkey':['a','b','d'],'data2':range(3)})

df4
  • 1
  • 2
  • 3
data2 rkey
0 0 a
1 1 b
2 2 d
df3.merge(df4,left_on = 'lkey',right_on = 'rkey',how = 'inner')
  • 1
data1 lkey data2 rkey
0 0 b 1 b
1 1 b 1 b
2 6 b 1 b
3 2 a 0 a
4 4 a 0 a
5 5 a 0 a

2、多對多的合併(一個表的連線鍵列有重複值,另一個表中的連線鍵有重複值)

df1 = pd.DataFrame({'key':['b','b','a','c','a','a','b'],'data1': range(7)})

df1
  • 1
  • 2
  • 3
data1 key
0 0 b
1 1 b
2 2 a
3 3 c
4 4 a
5 5 a
6 6 b
df5 = pd.DataFrame({'key':['a','b','a','b','b'],'data2': range(5)})
df5
  • 1
  • 2
data2 key
0 0 a
1 1 b
2 2 a
3 3 b
4 4 b
df1.merge(df5)
  • 1
data1 key data2
0 0 b 1
1 0 b 3
2 0 b 4
3 1 b 1
4 1 b 3
5 1 b 4
6 6 b 1
7 6 b 3
8 6 b 4
9 2 a 0
10 2 a 2
11 4 a 0
12 4 a 2
13 5 a 0
14 5 a 2

合併小結

1)預設情況下,會將兩個表中相同列名作為連線鍵

2)多對多,會採用笛卡爾積形式連結(左表連線鍵有三個值‘1,3,5’,右表有兩個值‘2,3’,則會形成,(1,2)(1,3)(3,1),(3,2)。。。6種組合)

3)存在多個連線鍵的處理

left = pd.DataFrame({'key1':['foo','foo','bar'],'key2':['one','one','two'],'lval':[1,2,3]})

right = pd.DataFrame({'key1':['foo','foo','bar','bar'],'key2':['one','one','one','two'],'rval':[4,5,6,7]})
  • 1
  • 2
  • 3
  • 4
left
  • 1
key1 key2 lval
0 foo one 1
1 foo one 2
2 bar two 3
right
  • 1
key1 key2 rval
0 foo one 4
1 foo one 5
2 bar one 6
3 bar two 7
pd.merge(left,right,on = ['key1','key2'],how = 'outer')
  • 1
key1 key2 lval rval
0 foo one 1.0 4
1 foo one 1.0 5
2 foo one 2.0 4
3 foo one 2.0 5
4 bar two 3.0 7
5 bar one NaN 6

1)連線鍵是多對多關係,應執行笛卡爾積形式

2)多列應看連線鍵值對是否一致

4)對連線表中非連線列的重複列名的處理

pd.merge(left,right,on = 'key1')
  • 1
key1 key2_x lval key2_y rval
0 foo one 1 one 4
1 foo one 1 one 5
2 foo one 2 one 4
3 foo one 2 one 5
4 bar two 3 one 6
5 bar two 3 two 7
pd.merge(left,right,on = 'key1',suffixes = ('_left','_right'))
  • 1
key1 key2_left lval key2_right rval
0 foo one 1 one 4
1 foo one 1 one 5
2 foo one 2 one 4
3 foo one 2 one 5
4 bar two 3 one 6
5 bar two 3 two 7

2)索引上的合併

當連線鍵位於索引中時,成為索引上的合併,可以通過merge函式,傳入left_index、right_index來說明應該被索引的情況。

  1. 一表中連線鍵是索引列、另一表連線鍵是非索引列
left1 = pd.DataFrame({'key':['a','b','a','a','b','c'],'value': range(6)})
left1
  • 1
  • 2
key value
0 a 0
1 b 1
2 a 2
3 a 3
4 b 4
5 c 5
right1 = pd.DataFrame({'group_val':[3.5,7]},index = ['a','b'])
right1
  • 1
  • 2
group_val
a 3.5
b 7.0
pd.merge(left1,right1,left_on = 'key',right_index = True)
  • 1
key value group_val
0 a 0 3.5
2 a 2 3.5
3 a 3 3.5
1 b 1 7.0
4 b 4 7.0

有上可知,left_on、right_on是指定表中非索引列為連線鍵,left_index、right_index是指定表中索引列為連線鍵,兩者可以組合,是為了區分是否是索引列

  1. 兩個表中的索引列都是連線鍵
left2 = pd.DataFrame(np.arange(6).reshape(3,2),index = ['a','b','e'],columns = ['0hio','nevada'])

right2 = pd.DataFrame(np.arange(7,15).reshape(4,2),index = ['b','c','d','e'],columns = ['misso','ala'])

left2
  • 1
  • 2
  • 3
  • 4
  • 5
0hio nevada
a 0 1
b 2 3
e 4 5
right2
  • 1
misso ala
b 7 8
c 9 10
d 11 12
e 13 14
pd.merge(left2,right2,left_index = True,right_index = True,how = 'outer')
  • 1
0hio nevada misso ala
a 0.0 1.0 NaN NaN
b 2.0 3.0 7.0 8.0
c NaN NaN 9.0 10.0
d NaN NaN 11.0 12.0
e 4.0 5.0 13.0 14.0

3)軸向連線

在這裡展示一種新的連線方法,對應於numpy的concatenate函式,pandas有concat函式

#numpy
arr =np.arange(12).reshape(3,4)
  • 1
  • 2
arr
  • 1
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11]])
  • 1
  • 2
  • 3
  • 4
np.concatenate([arr,arr],axis = 1)#橫軸連線塊
  • 1
    array([[ 0,  1,  2,  3,  0,  1,  2,  3],
           [ 4,  5,  6,  7,  4,  5,  6,  7],
           [ 8,  9, 10, 11,  8,  9, 10, 11]])
  • 1
  • 2
  • 3
  • 4

concat函式引數表格

引數 說明
objs 參與連線的列表或字典,且列表或字典裡的物件是pandas資料型別,唯一必須給定的引數
axis=0 指明連線的軸向,0是縱軸,1是橫軸,預設是0
join ‘inner’(交集),‘outer’(並集),預設是‘outer’指明軸向索引的索引是交集還是並集
join_axis 指明用於其他n-1條軸的索引(層次化索引,某個軸向有多個索引),不執行交併集
keys 與連線物件有關的值,用於形成連線軸向上的層次化索引(外層索引),可以是任意值的列表或陣列、元組資料、陣列列表(如果將levels設定成多級陣列的話)
levels 指定用作層次化索引各級別(內層索引)上的索引,如果設定keys的話
names 用於建立分層級別的名稱,如果設定keys或levels的話
verify_integrity 檢查結果物件新軸上的重複情況,如果發橫則引發異常,預設False,允許重複
ignore_index 不保留連線軸上的索引,產生一組新索引range(total_length)
s1 = pd.Series([0,1,2],index = ['a','b','c'])

s2 = pd.Series([2,3,4],index = ['c','f','e'])

s3 = pd.Series([4,5,6],index = ['c','f','g'])
  • 1
  • 2
  • 3
  • 4
  • 5
pd.concat([s1,s2,s3])#預設並集、縱向連線
  • 1

a 0 b 1 c 2 c 2 f 3 e 4 c 4 f 5 g 6 dtype: int64

pd.concat([s1,s2,s3],ignore_index = True)#生成縱軸上的並集,索引會自動生成新的一列
  • 1

0 0 1 1 2 2 3 2 4 3 5 4 6 4 7 5 8 6 dtype: int64

pd.concat([s1,s2,s3],axis = 1,join = 'inner')#縱向取交集,注意該方法對物件表中有重複索引時失效
  • 1
0 1 2
c 2 2 4
pd.concat([s1,s2,s3],axis = 1,join = 'outer')#橫向索引取並集,縱向索引取交集,注意該方法對物件表中有重複索引時失效
  • 1
0 1 2
a 0.0 NaN NaN
b 1.0 NaN NaN
c 2.0 2.0 4.0
e NaN 4.0 NaN
f NaN 3.0 5.0
g NaN NaN 6.0

concat函式小結

1)縱向連線,ignore_index = False ,可能生成重複的索引

2)橫向連線時,物件索引不能重複

4)合併重疊資料

適用範圍:

1)當兩個物件的索引有部分或全部重疊時

2)用引數物件中的資料為呼叫者物件的缺失資料‘打補丁’

a = pd.Series([np.nan,2.5,np.nan,3.5,4.5,np.nan],index = ['a','b','c','d','e','f'])

b = pd.Series(np.arange(len(a)),index = ['a','b','c','d','e','f'])
  • 1
  • 2
  • 3
a
  • 1
a    NaN
b    2.5
c    NaN
d    3.5
e    4.5
f    NaN
dtype: float64
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
b
  • 1
a    0
b    1
c    2
d    3
e    4
f    5
dtype: int32
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
a.combine_first(b)#利用b填補了a的空值
  • 1
a    0.0
b    2.5
c    2.0
d    3.5
e    4.5
f    5.0
dtype: float64
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
a = pd.Series([np.nan,2.5,np.nan,3.5,4.5,np.nan],index = ['g','b','c','d','e','f'])
  • 1
a.combine_first(b)#部分索引重疊
  • 1
a    0.0
b    2.5
c    2.0
d    3.5
e    4.5
f    5.0
g    NaN
dtype: float64
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

小結

本篇部落格主要講述了一下內容:

1) merge函式合併資料集

2)concat函式合併資料集

3)combine_first函式,含有重疊索引的缺失值填補