Learning Objectives
- 用 split-apply-combine 說明 groupby 做的三件事
- 用 groupby 加上 mean、count、size 算出各組的統計量,並說出 count 與 size 遇到缺值時的差別
- 用 agg 一次算出好幾個統計量,再排序、四捨五入、畫成長條圖
- 依兩個欄位分組,讀懂多層索引的結果
各系的平均是多少?
很多分析問題的形式都是「每一組的某個統計量是多少」:各系的平均讀書時數、各課程的期末平均、每棟宿舍每月的用電量。
用迴圈也做得到:先找出所有系所,再一個系一個系篩選、計算、存起來。pandas 把這整套步驟包成一個方法 groupby。
groupby 做的事可以拆成三步,稱為 split-apply-combine:
| 步驟 | 做什麼 | 例子 |
|---|---|---|
| split(分) | 依某一欄的值把資料表切成好幾塊 | 依「系所」切成資工、中文、物理三塊 |
| apply(算) | 每一塊各自計算 | 每一塊算期末平均 |
| combine(合) | 把各塊的結果合成一個新的表 | 一個以系所為索引的 Series |
這一課的資料是 grades.csv(600 筆修課成績)與 students.csv(200 位學生),都是程式產生的模擬資料,不是任何學校的真實資料。
逐步看:groupby 把表切成幾塊
先用一個只有 6 列的小表。注意右邊記憶體區:迴圈每跑一圈,part 就是其中一塊資料表。
一次算好幾個統計量:agg
groupby(...)["欄"] 後面接的方法決定 apply 那一步算什麼:
| 方法 | 每一組算出 |
|---|---|
mean()、median() |
平均、中位數 |
sum()、min()、max() |
總和、最小、最大 |
std() |
標準差(第 15 課) |
count() |
不是缺值的筆數 |
size() |
列數(含缺值) |
想同時看好幾個統計量,用 agg 傳入名稱串列:agg(["count", "mean", "std"]),結果是一個資料表,每個統計量一欄。
接著常做的三件事:round(1) 四捨五入、sort_values("mean") 依某一欄排序、畫成長條圖比較。
依兩個欄位分組:groupby(["dept", "dorm"]) 會把「系所 × 是否住宿」的每一種組合當成一組。
結果的索引有兩層(多層索引,MultiIndex),印出來時外層相同的值只寫一次。
逐步看:各課程的期末成績,以及兩個欄位分組
這次讀入整份 grades.csv。最後一步會畫出長條圖,圖出現在輸出區下方。
count 與 size:缺值算不算一筆?
grades.csv 的期中考有幾筆缺考,記成缺值(NaN,第 7 課)。這時 count 和 size 的結果不同:
size 數的是列數,count 數的是那一欄有值的筆數。算平均時,mean 也會自動略過缺值,
所以「平均是幾個人算出來的」要看 count,不是 size。
逐步看:每一門課有幾人缺考
實作:各系的每週讀書時數
讀入 students.csv,依系所(dept)分組,對每週讀書時數(study_hours)算出人數(count)與平均(mean),
四捨五入到小數 1 位,依平均由大到小排序後印出。
小測驗:分組彙總
df.groupby("系所")["期末"].mean() 裡,哪一部分對應 split-apply-combine 的 apply?
某一組有 10 列,其中 2 列的「期中」是缺值。這一組的 ["期中"].size() 與 ["期中"].count() 各是多少?
students.groupby(["dept", "dorm"])["study_hours"].mean() 的結果有幾層索引?
下面程式會印出什麼?
import pandas as pd
df = pd.DataFrame({"g": ["a", "b", "a"], "v": [1, 2, 5]})
print(df.groupby("g")["v"].sum().to_dict())
重點整理
groupby做三件事:依某欄的值切成好幾組、每組各自算、再合成一個結果(split-apply-combine)。groupby("欄")["要算的欄"].mean();常用的還有median、sum、min、max、std、count、size。count只數有值的筆數,size數列數;平均、總和都會略過缺值。agg(["count", "mean", "std"])一次算好幾個統計量,結果是資料表;之後常接round、sort_values與畫圖。- 依兩個欄位分組,結果有兩層索引。
- 下一課把兩份資料表依共同的欄位合併,例如把成績和學生的系所接起來,就能算「各系的期末平均」。