Pandas 學習筆記(一)concat與merge
前言
筆者平常比較習慣熟悉R的操作,不過近日覺得scikit learn真的太好用了,想要逐漸將開發重心慢慢轉往python。但是這件事不太可能一蹴可幾,將R語言裡平常慣用的數據清洗手法,思考怎麼在python實現,這可能是比較好的做法。
雖然不能百分百完全移植,因為不同語言有不同的架構思維,但是基本的功能應是可行的。
我們想實現類似R的幾種功能,以下將紀錄R與python對應的實現方式
- rbind
- cbind
- left_join、right_join、inner_join
1 | import pandas as pd |
1 | print(df1) |
a b c d
1 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 0.0
3 0.0 0.0 0.0 0.0
1 | print(df2) |
a b c d
1 1.0 1.0 1.0 1.0
2 1.0 1.0 1.0 1.0
3 1.0 1.0 1.0 1.0
1 | print(df3) |
c d e f
1 2.0 2.0 2.0 2.0
2 2.0 2.0 2.0 2.0
3 2.0 2.0 2.0 2.0
1 | print(df4) |
c d e f
2 2.0 2.0 2.0 2.0
3 2.0 2.0 2.0 2.0
5 2.0 2.0 2.0 2.0
cbind、rbind的實現:pd.concat
concat
設定 axis=0
為直向合併,axis=1
為橫向合併
DataFrame.append()
類似於axis=0
1 | print(pd.concat([df1,df3],axis=1)) |
a b c d c d e f
1 0.0 0.0 0.0 0.0 2.0 2.0 2.0 2.0
2 0.0 0.0 0.0 0.0 2.0 2.0 2.0 2.0
3 0.0 0.0 0.0 0.0 2.0 2.0 2.0 2.0
1 | print(pd.concat([df1,df2],axis=0)) |
a b c d
1 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 0.0
3 0.0 0.0 0.0 0.0
1 1.0 1.0 1.0 1.0
2 1.0 1.0 1.0 1.0
3 1.0 1.0 1.0 1.0
但是可以看到上一個data frame中index並不連續,可以用ignore_index = True
產生新的index
可以注意到index由012012變為012345
1 | print(pd.concat([df1,df2],axis=0,ignore_index = True)) |
a b c d
0 0.0 0.0 0.0 0.0
1 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 0.0
3 1.0 1.0 1.0 1.0
4 1.0 1.0 1.0 1.0
5 1.0 1.0 1.0 1.0
還有一個參數是join='outer'
(這是預設的),另外一個則為join='inner'
如果是outer
,沒有的資料會用NaN
替代,使用inner
的話,會只保留兩個df共同都有資料的欄位
1 | print(pd.concat([df1,df3],axis=0,join='outer')) |
a b c d e f
1 0.0 0.0 0.0 0.0 NaN NaN
2 0.0 0.0 0.0 0.0 NaN NaN
3 0.0 0.0 0.0 0.0 NaN NaN
1 NaN NaN 2.0 2.0 2.0 2.0
2 NaN NaN 2.0 2.0 2.0 2.0
3 NaN NaN 2.0 2.0 2.0 2.0
1 | print(pd.concat([df1,df3],axis=0,join='inner')) |
c d
1 0.0 0.0
2 0.0 0.0
3 0.0 0.0
1 2.0 2.0
2 2.0 2.0
3 2.0 2.0
join_axes
功能,用於水平合併時指定index參考者
df1的index是123,df4的index是235,來看看參數不同會發生什麼事
1 | print(pd.concat([df1,df4],axis=1, join_axes=[df1.index])) |
a b c d c d e f
1 0.0 0.0 0.0 0.0 NaN NaN NaN NaN
2 0.0 0.0 0.0 0.0 2.0 2.0 2.0 2.0
3 0.0 0.0 0.0 0.0 2.0 2.0 2.0 2.0
1 | print(pd.concat([df1,df4],axis=1, join_axes=[df4.index])) |
a b c d c d e f
2 0.0 0.0 0.0 0.0 2.0 2.0 2.0 2.0
3 0.0 0.0 0.0 0.0 2.0 2.0 2.0 2.0
5 NaN NaN NaN NaN 2.0 2.0 2.0 2.0
1 | print(pd.concat([df1,df4],axis=1, join_axes=None)) |
a b c d c d e f
1 0.0 0.0 0.0 0.0 NaN NaN NaN NaN
2 0.0 0.0 0.0 0.0 2.0 2.0 2.0 2.0
3 0.0 0.0 0.0 0.0 2.0 2.0 2.0 2.0
5 NaN NaN NaN NaN 2.0 2.0 2.0 2.0
以上我感覺到python對於index的處理,應該是比R還要嚴謹的
join系列的實現:merge
1 | list1=[['1101','1101','1101','2330','2330','2330','2337','2337','2337'], |
1 | print(df1) |
code date price
0 1101 20180101 10
1 1101 20180102 11
2 1101 20180103 12
3 2330 20180101 100
4 2330 20180102 101
5 2330 20180103 102
6 2337 20180101 201
7 2337 20180102 202
8 2337 20180103 203
1 | print(df2) |
Volume code date
0 200 1101 20180101
1 400 1101 20180103
2 20000 2330 20180101
3 20000 2330 20180103
4 5000 2337 20180101
5 5000 2337 20180103
以code以及date來合併,在R是寫成left_join(df1,df2,by=c('code'='code','date'=date'))
以下用Python來實現
1 | print(pd.merge(df1,df2, on=['code','date'],how='left')) |
code date price Volume
0 1101 20180101 10 200.0
1 1101 20180102 11 NaN
2 1101 20180103 12 400.0
3 2330 20180101 100 20000.0
4 2330 20180102 101 NaN
5 2330 20180103 102 20000.0
6 2337 20180101 201 5000.0
7 2337 20180102 202 NaN
8 2337 20180103 203 5000.0
只要改變how=''
就可以改為inner_join、right_join等等…不過我目前也只用到leftjoin
可以發現R可以把兩個column name不同但是內容相同的column接在一起,merge當然也可以
以下我們把colname改一下,來試著合併看看
1 | dict1={'code' : list1[0], 'date' : list1[1], 'price' : list1[2]} |
1 | print(pd.merge(df1, df2, left_on=['code','date'], right_on=['Ticker','Date'],how='left')) |
code date price Date Ticker Volume
0 1101 20180101 10 20180101 1101 200.0
1 1101 20180102 11 NaN NaN NaN
2 1101 20180103 12 20180103 1101 400.0
3 2330 20180101 100 20180101 2330 20000.0
4 2330 20180102 101 NaN NaN NaN
5 2330 20180103 102 20180103 2330 20000.0
6 2337 20180101 201 20180101 2337 5000.0
7 2337 20180102 202 NaN NaN NaN
8 2337 20180103 203 20180103 2337 5000.0
不過R會把第二個df的拿來當merge key的column自動刪掉,Python並不會