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並不會
