owned this note
owned this note
Published
Linked with GitHub
Python + Pandas
===
Pandas 是 Python 的一個套件,用來處理 table 類的資料。
舉例來說,底下的表格示範了一個金磚國家 (brics) 的資訊
|country | capital | area | population|
|--------|--------|--------|--------|
|Brazil|brasilia|8.516|200.40|
|Russia|Moscow|17.100|143.50|
|India|New Delhi|3.286|1252.00|
|China|Beijing|9.597|1357.00|
|South Africa|Pretoria|1.221|52.98|
這個表格就可以使用 Pandas 來表示。
## 和 Numyp Array 不同之處
Numpy 的 array 也可以處理 table 類的資料,但 numpy array 有一個 **限制**,那就是要求資料要「同一型別」。
要求同一型別主要是為了最佳化的關係,如此一來, numpy 可以高效的處理資料。但同時也喪失了彈性。
由前面的表格可以看到,表格中包含了字串資料,浮點數資料…如果混在一起,就無法使用 Numpy array 來處理了。
因此就有 Pandas 的出現。它是架構在 Numpy 之上,提供了一個彈性的框架,可以處理 table 類的資料,又可以混用型別。
## 匯入 Pandas 的套件
使用底下的語法匯入 Pandas。
```python=
import pandas as pd
```
## 最常用的資料結構 DataFrame
Pandas 中最常用的資料結構是 *DataFrame*,它本身為一個 2 維的表格。
要如何產生 DataFrame 呢?常見的方法是使用 Python 的 dictionary 來建構 DataFrame.
```python=
#建構一個 dictionary
dict = {
"country":["Brazil", "Russia", "India", "China", "South Africa"],
"capital":["Brasilia", "Moscow", "New Delhi", "Beijing", "Pretoria"],
"area":[8.516, 17.10, 3.286, 9.597, 1.221],
"population":[200.4, 143.5, 1252, 1357, 52.98] }
import pandas as pd
brics = pd.DataFrame(dict)
brics
```
結果會輸出 (在 Jupyter notebook 下)
![](https://i.imgur.com/u3OK998.png)
注意上一張圖中,第 0 個 column 為 row 的 *label*,它都是 0, 1, 2 的數字,我們可以使用 index 的指令幫它加上一個 row label。
```python=
brics.index = ["BR", "RU", "IN", "CH", "SA"]
brics
```
結果如下所示,可以看出來,底下的面一個 row 前面,都加上了一個 index
![](https://i.imgur.com/Giq8wFo.png)
## 由外部讀檔案,建立 DataFrame
另一個建立 DataFrame 的方式,其實是由外部讀檔進來。
例如底下的資料存在一個 brics.csv 的檔案中
,country,capital,area,population
BR,Brazil,Brasilia,8.516,200.4
RU,Russia,Moscow,17.10,143.5
IN,India,New Delhi,3.286,1252
CH,China,Beijing,9.597,1357
SA,South Africa,Pretoria,1.221,52.98
那可以使用 read_csv 將資料讀入。
```python=
brics = pd.read_csv("brics.csv")
brics
```
會得到底下的結果
![](https://i.imgur.com/cVYHeJL.png)
可以看到,第 0 個 column 是 unnamed。我們可以加入 index_col 的參數,跟 Pandas 講第 0 個 column 代表的 row 的 label。
```python=
brics = pd.read_csv("brics.csv", index_col = 0)
brics
```
結果如下圖,可以看出每個 row 的 label 都指定好了。
![](https://i.imgur.com/p7yaEgx.png)
## 為什麼要在意 label??
為什麼要替 row 上加入 label? 因為 Pandas 在存取資料時,可以用 index 取資料,也可以用 label 取資料 (底下會說明)。所以替每個 row 加上 label,會有助於之後程式的撰寫。
# 如何取得 DataFrame 中的資料
這節要談談如何由 DataFrame 中取得資料。
我們會想取得:
- 某個 column 的資料
- 某些 columns 的資料
- 某個 row 的資料
- 某些 rows 的資料
- 某個格子的資料
底下會一個一個談到如何取得資料。
在瞭解要如何取得資料前,先看看 Pandas 的資料結構。
## 資料結構
底下的圖取自[這裏](http://bookdata.readthedocs.io/en/latest/base/01_pandas.html),可以看出來,Pandas 的 DataFrames 是由一群 series 所組成。
![](https://i.imgur.com/ldoCBuo.png)
而 *Series* 則是 One dimensional labelled array。Series 的示意圖如下。這張圖取自[這兒](https://www.kdnuggets.com/2017/01/pandas-cheat-sheet.html)。可以看出來,series 是一維的資料,但每筆資料都有加上標籤 (即圖中的 index)。
![](https://i.imgur.com/8xpNOFy.png)
## 取得某個 column 的資料
可以透過 label 來取得某個 column 的資料。
```python=
brics["country"]
```
上述程式碼取得 country 的內容。結果如下
![](https://i.imgur.com/k7QhujJ.png)
而 brics['country'] 是一個 Series 型別,代表一個 1 維的 array。
我們可以透過底下的程式碼觀察 brics['country'] 的型別。
```python=
type(brics['country'])
```
結果如下
![](https://i.imgur.com/9VbsMfR.png)
那如果要取得多個 column 的資料呢?那就不能依靠 series 這個資料結構了。因為 series 一次就代表一個一維的資料串列。
多個 column 的資料,就要靠 DataFrame 了。
## 取得多個 columns
底下的程式碼可以取得 country 以及 capital 兩個 column 的內內容。
```python=
brics[['country', 'capital']]
```
結果如下:
![](https://i.imgur.com/Y33KqzT.png)
這個結果可視為原本 table 的一個 **子table**。
所以 brics[['country', 'capital']] 其實也是個 DataFrame。
要注意,中括號中還有一個中括號!
另一個要注意的是,Pandas 用中括號時,是取得 column 的資料,但我們一般在存取 2 維陣列時,若給中括號,取的是 row 的資料。這點 Pandas 和我們的習慣不一樣,要注意。
## 取得一個 rows 的資料
使用 slice 的語法即可,例如想取得索引值為 1 的 row
```python=
brics[1:2]
```
## 取得多個 rows 的資料
我們可以用 slice 的語法取得某些 rows 的資料。
```python=
brics[1:3]
```
會將索引值 1~2 的 rows 取出來,成為一個 DataFrame。
![](https://i.imgur.com/eP84KZd.png)
# 使用 loc 以及 iloc 取得 DataFrame 中的資料
loc 以及 iloc 是 Pandas 中常用來取資料的函式,這兩個的區別如下:
- **loc**:*label-based* 的取資料的方式。要取資料時,要給定 label 來取資料。
- **iloc**: *index-based* 的取資料的方式。要取資料時,給定索引值來取資料。
## 使用 loc 來取得資料
### 取得 row 的資料
取得某一個 row 的資料,可以使用底下的語法
```python=
#取得 BR 這個 row 的資料
brics.loc['BR']
```
結果如下圖所示
![](https://i.imgur.com/g0oc4td.png)
可以看出,要取得資料時,要指定一個標籤 (label),這就是為什麼 loc 為 label-based 的取資料的方式。
上面取得的資料是一個 series。如果要取得 DataFrame,那就要使用兩個 []。
```python=
#注意有兩個 []
brics.loc[['BR']]
```
結果如下。
![](https://i.imgur.com/XGgAZQw.png)
可以看出來,DataFrame 的方式比較友善,取得一個 row,就是用橫的方式展示,不像是取得 series 的方式,是以直行的方式來展示。
我們也可以取得多個 rows 的資料。例如想取得 'BR', 'RU', 以及 'CH' 三列的資料,可以用如下的語法。
```python=
brics.loc[['BR', 'RU', 'CH']]
```
結果如下所示
![](https://i.imgur.com/GF62BLT.png)
### 取得 row 以及 column 的資料
只要指定 row 以及 column,即可得到特定 row 及 column 的資料。
```python=
brics.loc[['BR', 'RU', 'CH'], ['area', 'country']]
```
結果如下所示
![](https://i.imgur.com/VGZO4GX.png)
那如果想取得特定的 column 呢?把 row 的部分用 : 取代即可。
```python=
brics.loc[:, ['area', 'country']]
```
結果如下
![](https://i.imgur.com/HAlusy8.png)
## 使用 iloc 取得資料
iloc 是使用 index 來取得資料的方式,和其他程式語言存取陣列資料的方式十分相似。
iloc 和 loc 很像,只是把 label 換成對應的 index 即可。
底下的表格展示了每個 column 以及 row 的索引。唯一要注意的是,**索引是由 0 開始囉**。
| |row index |0|1|2|3|
|--------|--------|--------|--------|--------|--------|
|column index |column/row label |country | capital | area | population|
|0|BR|Brazil|brasilia|8.516|200.40|
|1|RU|Russia|Moscow|17.100|143.50|
|2|IN|India|New Delhi|3.286|1252.00|
|3|CH|China|Beijing|9.597|1357.00|
|4|SA|South Africa|Pretoria|1.221|52.98|
### 取得 row 的資料
```python=
#注意有兩個 []
brics.loc[['BR']]
#對應的 iloc 寫法
brics.iloc[[0]]
```
### 取得多個 row 的資料
```python=
# loc 的語法
brics.loc[['BR', 'RU', 'CH']]
# iloc 的語報
brics.loc[[0, 1, 3]]
```
### 取得 row 及 column 的資料
```python=
# loc 的語法
brics.loc[['BR', 'RU', 'CH'], ['area', 'country']]
# iloc 的語法
brics.loc[[0, 1, 3], [2, 0]]
```
### 取得特定 column 的資料
同樣使用 slice 來處理
```python=
#loc 語法
brics.loc[:, ['area', 'country']]
#iloc 語法
brics.loc[:, [2, 0]]
```
## 整理
### 使用 [] 來取得資料
用 [] 只能用來取 column 的資料。
[] 預設是取得 column 的資料
如果想取得 row 的資料,只能用 slice 的方式來取得。
### loc 以及 iloc 取得資料
(i)loc 取得資料的方式比較彈性,可以取得 row,column,或是 row+column 的方式取得資料。
(i)loc 預設是取得 row 的資料。
(i)loc 比起 [] 的另一個優勢是,它的語義是接近傳統存取二維陣列的取法。也就是 row 的存取優先,然後再指定 column。
### 取得 Series 或是 DataFrame
無論是 [], loc 或是 iloc 的方式,取得 DataFrame 都需要使用兩個 []。
# 參考資料
- [BookData](http://bookdata.readthedocs.io/en/latest/base/01_pandas.html)
- [Pandas Cheat Sheet: Data Science and Data Wrangling in Python](https://www.kdnuggets.com/2017/01/pandas-cheat-sheet.html)
- [Python Pandas Tutorial 2: Dataframe Basics](https://www.youtube.com/watch?v=F6kmIpWWEdU)。這是個 Youtube 頻道,有數位人訂閱
- [DataCamp Pandas 的課程](https://www.datacamp.com/home)