在數據分析中,我們經常會希望整理出一個分組後的統計表格。 例如:假設我們有一份學生考試成績的資料表格,我們可能會想知道「每個班級的平均成績」是多少。
data = {
'班級': ['A', 'A', 'B', 'B', 'B', 'C', 'C'],
'姓名': ['小明', '小美', '小華', '小強', '小美', '小安', '小傑'],
'性別': ['男', '女', '男', '男', '女', '女', '男'],
'成績': [85, 90, 78, 82, 88, 95, 91],
'缺席次數': [2, 0, 3, 1, 0, 0, 2]
}
df = pd.DataFrame(data)
結果呈現如下:
班級 姓名 性別 成績 缺席次數
0 A 小明 男 85 2
1 A 小美 女 90 0
2 B 小華 男 78 3
3 B 小強 男 82 1
4 B 小美 女 88 0
5 C 小安 女 95 0
6 C 小傑 男 91 2
這時候,就需要將資料依照「班級」進行分組,再計算「成績」的平均值。
這類分組與彙總的操作,就可以透過 pandas 的 groupby
或 pivot_table
來實現。
group_by #
基本語法 #
df.groupby("col_name")
會根據 col_name
把大家分組,例如,col_name
為班級
的話,上述的表的內容就會依據班級而被分為三組(A、B、C)。由於運行之後得到的是類似三張表格的東西,所以他不是一個有效的表格數據,不能直接用 print 呈現出來。如果想要能夠看到相關的數值,我們需要先提取我們關注的其他 column,再使用“聚合函數”,例如 mean, sum
. 例如:我們在乎的是每個班級的平均成績,
df.groupby("班級")["成績"].mean()
我們就能得到結果:
班級
A 87.500000
B 82.666667
C 93.000000
Name: 成績, dtype: float64
如果我們不只是在乎成績,還在乎班級的缺席次數我們可以把 list 傳入方括中:
df.groupby("班級")[["成績","缺席次數"]].mean()
就能得到下面一張表格:
成績 | 缺席次數 | |
---|---|---|
班級 | ||
A | 87.500000 | 1.000000 |
B | 82.666667 | 1.333333 |
C | 93.000000 | 1.000000 |
我們還可以根據班級+性別
來進行分組計算平均成績和缺席次數:
df.groupby(["班級", "性別"])[["成績","缺席次數"]].mean()
成績 | 缺席次數 | ||
---|---|---|---|
班級 | 性別 | ||
A | 女 | 90.0 | 0.0 |
男 | 85.0 | 2.0 | |
B | 女 | 88.0 | 0.0 |
男 | 80.0 | 2.0 | |
C | 女 | 95.0 | 0.0 |
男 | 91.0 | 2.0 |
一次使用多個聚合函數 #
如果我們不只是想知道平均成績,還想知道加總成績,我們可以使用 agg
,它可以一次性讓我們知道多個聚合函數的結果:
df.groupby("班級")["成績"].agg(['mean', 'sum'])
就能得到:
mean | sum | |
---|---|---|
班級 | ||
A | 87.500000 | 175 |
B | 82.666667 | 248 |
C | 93.000000 | 186 |
自定義聚合函數 #
再來我們還可以自己定義聚合函數,這很簡單,只需要自己定義好函數後,使用 apply
. 例如:
df.groupby("班級")["成績"].apply(function)
pivot_table #
雖然 groupby
非常強大,但在一些資料展示與整理的情境中,使用 pivot_table
可以更快速地產出「表格式」的總結結果。和 groupby
一樣,pivot_table
也可以做分組彙總,不同的是,它會自動幫你整理成橫向與縱向都有對齊的表格格式,非常適合做報表。
基本語法 #
pd.pivot_table(df, index="班級", values="成績", aggfunc="mean")
成績 | |
---|---|
班級 | |
A | 87.500000 |
B | 82.666667 |
C | 93.000000 |
也可以一次計算多個欄位的平均值:
pd.pivot_table(df, index="班級", values=["成績", "缺席次數"], aggfunc="mean")
加上 columns:分群之後再分類 #
如果你希望能看出「每個班級中,男生與女生的成績平均」呢?這時候就可以加上 columns="性別"
:
pd.pivot_table(df, index="班級",values="成績", columns="性別", aggfunc="mean")
性別 | 女 | 男 |
---|---|---|
班級 | ||
A | 90.0 | 85.0 |
B | 88.0 | 80.0 |
C | 95.0 | 91.0 |
同時搭配多個值欄位 + 多個 columns #
最後,如果我們想一次看到「每個班級、每個性別」的平均「成績」與「缺席次數」,就可以這樣寫:
pd.pivot_table(
df,
values=["成績", "缺席次數"],
index="班級",
columns="性別",
aggfunc="mean"
)
就能得到:
成績 | 缺席次數 | |||
---|---|---|---|---|
性別 | 女 | 男 | 女 | 男 |
班級 | ||||
A | 90.0 | 85.0 | 0.0 | 2.0 |
B | 88.0 | 80.0 | 0.0 | 2.0 |
C | 95.0 | 91.0 | 0.0 | 2.0 |