National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 09

分組彙總

split-apply-combine、agg、多欄分組
Interaction實作 30 minute(s)

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 就是其中一塊資料表。

互動練習:split、apply、combine

一個 8 列的小表,期中有兩格是缺值(NaN)。選分組欄與彙總函數,按「執行」看三個步驟;照下面的任務做一遍。

一次算好幾個統計量: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 位,依平均由大到小排序後印出。

你的輸出
預期輸出

小測驗:分組彙總

1.

df.groupby("系所")["期末"].mean() 裡,哪一部分對應 split-apply-combine 的 apply?

2.

某一組有 10 列,其中 2 列的「期中」是缺值。這一組的 ["期中"].size() 與 ["期中"].count() 各是多少?

3.

students.groupby(["dept", "dorm"])["study_hours"].mean() 的結果有幾層索引?

4.

下面程式會印出什麼?

import pandas as pd
df = pd.DataFrame({"g": ["a", "b", "a"], "v": [1, 2, 5]})
print(df.groupby("g")["v"].sum().to_dict())
第 1 次作答

重點整理

  • groupby 做三件事:依某欄的值切成好幾組、每組各自算、再合成一個結果(split-apply-combine)。
  • groupby("欄")["要算的欄"].mean();常用的還有 median、sum、min、max、std、count、size。
  • count 只數有值的筆數,size 數列數;平均、總和都會略過缺值。
  • agg(["count", "mean", "std"]) 一次算好幾個統計量,結果是資料表;之後常接 round、sort_values 與畫圖。
  • 依兩個欄位分組,結果有兩層索引。
  • 下一課把兩份資料表依共同的欄位合併,例如把成績和學生的系所接起來,就能算「各系的期末平均」。
這一課完成了!
Next lesson:合併資料表
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。