Pandas數(shù)據(jù)透視表pivot_table的使用小結(jié)
數(shù)據(jù)分析師大概都有過這樣的經(jīng)歷——面對一張幾萬行的原始數(shù)據(jù)表,老板要的是"按地區(qū)、按季度、按產(chǎn)品類別"的匯總報表,而你手里只有一堆散亂的流水記錄。這時候,pivot_table 就是你最得力的工具。它不是什么高深的黑魔法,本質(zhì)上就是把"長條形"的原始數(shù)據(jù),折疊成一張人人看得懂的二維匯總表——同時完成分組、聚合、重塑三件事,一行代碼搞定。
一、先搞清楚它在做什么
pivot_table 的工作邏輯,拆開來看其實只有三步:
第一步,分組。 按照你指定的 index 和 columns 字段,把數(shù)據(jù)切成若干個小格子——就像把一張大桌子劃分成行和列的網(wǎng)格。
第二步,聚合。 每個格子里可能有多條記錄,用 aggfunc 指定的函數(shù)(求和、均值、計數(shù)……)把它們壓縮成一個數(shù)字。
第三步,重塑。 把壓縮后的結(jié)果擺進二維表格,行由 index 決定,列由 columns 決定,一張干凈的匯總表就成型了。
這里有個容易混淆的地方:pivot() 和 pivot_table() 長得很像,但前者要求每個行列組合唯一,遇到重復數(shù)據(jù)直接報錯;后者通過聚合函數(shù)處理重復值,日常工作中幾乎永遠用后者。同樣,groupby() 也能分組聚合,但輸出的是"長格式"結(jié)果,不會自動幫你鋪成二維表。三者各有用武之地,但要生成報表,pivot_table 是最直接的路。
二、把參數(shù)吃透
pandas.pivot_table(
data,
values=None,
index=None,
columns=None,
aggfunc='mean',
fill_value=None,
margins=False,
dropna=True,
margins_name='All',
observed=False, # pandas 2.2+ 建議顯式設為 True
sort=True
)
參數(shù)不多,但每一個都有講究,下面逐一說清楚:
| 參數(shù) | 類型 | 默認值 | 說明 |
|---|---|---|---|
| data | DataFrame | 必填 | 輸入數(shù)據(jù)源 |
| values | str / list | None | 要聚合的數(shù)值列;省略則對所有數(shù)值列聚合 |
| index | str / list | None | 行分組字段,傳列表可形成多層索引 |
| columns | str / list | None | 列分組字段,傳列表可形成多層列 |
| aggfunc | func / list / dict | 'mean' | 聚合函數(shù),支持字符串、函數(shù)、列表、字典 |
| fill_value | scalar | None | 聚合后產(chǎn)生的 NaN 用此值填充 |
| margins | bool | False | 是否在末尾添加行列匯總(小計/總計) |
| dropna | bool | True | 聚合前是否丟棄全為 NaN 的列 |
| margins_name | str | 'All' | 匯總行/列的標簽,可改成"合計"或"總計" |
| observed | bool | False | 僅對 Categorical 類型有效,True 則只展示實際出現(xiàn)的值 |
| sort | bool | True | 結(jié)果是否排序(v1.3.0 新增) |
有兩個參數(shù)特別容易被忽略,單獨說一下。
fill_value 和 dropna 經(jīng)常被當成同一回事,但它們作用的時機完全不同。dropna=True 發(fā)生在聚合之前,把含 NaN 的行直接丟掉;fill_value 發(fā)生在聚合之后,把結(jié)果表里出現(xiàn)的空格填上指定的值。兩者同時使用時,先丟后填,順序不能搞反。
observed 參數(shù)在 pandas 2.2 之后變得重要起來。如果分組字段是 Categorical 類型,默認的 observed=False 會把所有類別組合都列出來,哪怕某些組合在數(shù)據(jù)里根本不存在,結(jié)果表會憑空多出一堆全零的行。改成 observed=True 就只展示真實出現(xiàn)過的組合,干凈很多。
三、從零開始,跑通第一個例子
import pandas as pd
import numpy as np
df = pd.DataFrame({
"A": ["foo", "foo", "foo", "foo", "foo", "bar", "bar", "bar", "bar"],
"B": ["one", "one", "one", "two", "two", "one", "one", "two", "two"],
"C": ["small", "large", "large", "small", "small", "large", "small", "small", "large"],
"D": [1, 2, 2, 3, 3, 4, 5, 6, 7],
"E": [2, 4, 5, 5, 6, 6, 8, 9, 9]
})
最基礎的用法: 按 A、B 分行,按 C 分列,對 D 列求和。
table = pd.pivot_table(df, values='D', index=['A', 'B'],
columns=['C'], aggfunc="sum")
# C large small
# A B
# bar one 4.0 5.0
# two 7.0 6.0
# foo one 4.0 1.0
# two NaN 6.0
結(jié)果里出現(xiàn)了 NaN——因為 foo/two/large 這個組合在原始數(shù)據(jù)里不存在。加上 fill_value=0 就能填平:
table = pd.pivot_table(df, values='D', index=['A', 'B'],
columns=['C'], aggfunc="sum", fill_value=0)
對不同列用不同聚合函數(shù): 這是 aggfunc 字典語法最實用的地方——D 列求均值,E 列同時算最小值、最大值和均值。
table = pd.pivot_table(df, values=['D', 'E'], index=['A', 'C'],
aggfunc={'D': 'mean', 'E': ['min', 'max', 'mean']})
# 結(jié)果列變成多層,E 列下掛三個子列
四、真實場景里怎么用
銷售報表:最經(jīng)典的用法
季度銷售匯總大概是 pivot_table 被用得最多的場景。一張原始訂單表,幾行代碼變成管理層要的那種"行是季度、列是地區(qū)、格子里是銷售額"的報表:
data = {
'地區(qū)': ['華東', '華東', '華北', '華北', '華南', '華南'],
'產(chǎn)品': ['A', 'B', 'A', 'B', 'A', 'B'],
'季度': [1, 1, 1, 2, 2, 2],
'銷售額': [150000, 120000, 90000, 110000, 130000, 95000],
'利潤': [30000, 24000, 18000, 22000, 26000, 19000]
}
df_sales = pd.DataFrame(data)
pivot = pd.pivot_table(
data=df_sales,
values=['銷售額', '利潤'],
index='季度',
columns='地區(qū)',
aggfunc='sum',
fill_value=0,
margins=True,
margins_name='總計'
)
print(pivot)
margins=True 會自動在末尾追加一行一列的匯總,省去手動求和的麻煩。
時間維度分析:多層索引的威力
當你想同時按"地區(qū)"和"月份"分行時,把它們打包成列表傳給 index 就行,pandas 會自動生成多層索引:
df['月份'] = df['日期'].dt.month
pivot = pd.pivot_table(
data=df,
index=['地區(qū)', '月份'], # 兩級行索引
columns='產(chǎn)品',
values='銷售額',
aggfunc='sum'
)
生成的表格可以用 .xs() 切片訪問某一層:
pivot.xs('華東', level='地區(qū)') # 只看華東的數(shù)據(jù)
用戶行為分析:多函數(shù)同時上
想同時看"總訪問量"和"人均訪問次數(shù)"?一次搞定:
pivot = pd.pivot_table(
data=df_user,
index='用戶等級',
columns='訪問渠道',
values='訪問次數(shù)',
aggfunc=['sum', 'mean'],
fill_value=0
)
五、幾個讓結(jié)果更好用的技巧
自定義聚合函數(shù)
aggfunc 接受任意 Python 函數(shù),不局限于內(nèi)置統(tǒng)計量。比如想算極差(最大值減最小值):
pivot = pd.pivot_table(df, values='D', index='A',
aggfunc=lambda x: x.max() - x.min())
或者同時跑多個函數(shù):
pivot = pd.pivot_table(df, values='D', index='A',
aggfunc=['sum', 'mean', 'count', np.std])
扁平化多層列名
使用多個 aggfunc 時,結(jié)果列會變成 MultiIndex,導出 Excel 或做后續(xù)處理時很麻煩。一行代碼壓平:
pivot.columns = ['_'.join(col).strip() for col in pivot.columns.values]
# 原來的 ('sum', 'D') 變成 'sum_D',清爽很多
鏈式操作:透視完接著篩選
pivot_table 的結(jié)果是標準 DataFrame,可以直接接 query()、sort_values() 等操作:
result = (
pd.pivot_table(df, values='銷售額', index='地區(qū)', aggfunc='sum')
.reset_index()
.sort_values('銷售額', ascending=False)
.query('銷售額 > 100000')
)
六、幾種相近方法的橫向?qū)Ρ?/h2>
選哪個方法,取決于你的數(shù)據(jù)形態(tài)和目標輸出:
| 方法 | 支持重復值 | 支持聚合 | 輸出格式 | 最適合 |
|---|---|---|---|---|
| pivot() | ? | ? | 寬格式 | 數(shù)據(jù)唯一,純重塑 |
| pivot_table() | ? | ? 靈活 | 寬格式 | 匯總報表、多維分析 |
| groupby() | ? | ? 靈活 | 長格式 | 分組統(tǒng)計,結(jié)果靈活 |
| crosstab() | ? | ? 默認頻次 | 寬格式 | 交叉頻次統(tǒng)計 |
經(jīng)驗上來說:要生成"行×列"二維匯總表,首選 pivot_table;只需要對單列做分組統(tǒng)計,groupby 更簡潔;做問卷數(shù)據(jù)的交叉分析,crosstab 最順手。
七、綜合實戰(zhàn):電商訂單分析
把前面說的技巧都用上,跑一個完整的例子:
import pandas as pd
import numpy as np
np.random.seed(42)
n = 200
df = pd.DataFrame({
'地區(qū)': np.random.choice(['華東', '華北', '華南', '西部'], n),
'產(chǎn)品類別': np.random.choice(['電子', '服裝', '食品'], n),
'季度': np.random.choice([1, 2, 3, 4], n),
'銷售額': np.random.randint(1000, 50000, n),
'利潤': np.random.randint(100, 10000, n),
'訂單數(shù)': np.random.randint(1, 100, n)
})
# 多維透視:行=地區(qū)+季度,列=產(chǎn)品類別
# 銷售額求和,利潤求均值,末尾加總計
pivot = pd.pivot_table(
data=df,
values=['銷售額', '利潤'],
index=['地區(qū)', '季度'],
columns='產(chǎn)品類別',
aggfunc={'銷售額': 'sum', '利潤': 'mean'},
fill_value=0,
margins=True,
margins_name='匯總'
)
# 扁平化列名,方便后續(xù)處理
pivot.columns = ['_'.join(col) for col in pivot.columns]
print(pivot.head(10))
# 單獨看華東的數(shù)據(jù)
print(pivot.xs('華東', level='地區(qū)'))
寫在最后
pivot_table 的價值,在于它把"分組→聚合→重塑"這三步操作壓縮成了一行聲明式代碼,讓你把精力放在"我想看什么"上,而不是"怎么把數(shù)據(jù)搬來搬去"。
用熟之后,記住幾個核心習慣:index/columns 控制維度,aggfunc 字典語法處理異構(gòu)聚合,margins=True 自動加總計,fill_value 收拾稀疏數(shù)據(jù)的爛攤子,結(jié)果是標準 DataFrame,隨時可以接后續(xù)操作。
剩下的,就是多跑幾次真實數(shù)據(jù),感覺自然就來了。
參考資料
- pandas 官方 API 文檔:pandas.pivot_table
- pandas 官方用戶指南:Reshaping and pivot tables
- 華為云開發(fā)者社區(qū):深入探究Pandas中的透視表:基礎到高級應用全覆蓋
- 百度 Comate:Pandas數(shù)據(jù)透視表:多維度聚合與動態(tài)分析實戰(zhàn)指南
到此這篇關(guān)于Pandas數(shù)據(jù)透視表pivot_table的使用小結(jié)的文章就介紹到這了,更多相關(guān)Pandas數(shù)據(jù)透視表pivot_table內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
django xadmin action兼容自定義model權(quán)限教程
這篇文章主要介紹了django xadmin action兼容自定義model權(quán)限教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
使用Python?Matplotlib處理地理數(shù)據(jù)可視化
地理數(shù)據(jù)可視化是數(shù)據(jù)科學中一個重要的領(lǐng)域,它幫助我們理解和分析與地理位置相關(guān)的數(shù)據(jù),Python?提供了強大的工具來處理地理數(shù)據(jù),本文將介紹如何使用?Python?Matplotlib?處理地理數(shù)據(jù)可視化,包括基礎概念、常用庫、數(shù)據(jù)處理以及實際案例,需要的朋友可以參考下2024-11-11
Python中列表元素轉(zhuǎn)為數(shù)字的方法分析
這篇文章主要介紹了Python中列表元素轉(zhuǎn)為數(shù)字的方法,結(jié)合實例形式對比分析了Python列表操作及數(shù)學運算的相關(guān)技巧,需要的朋友可以參考下2016-06-06
Python數(shù)據(jù)可視化之Pandas、Matplotlib與Seaborn的高效實戰(zhàn)指南
本文介紹了Python數(shù)據(jù)可視化的綜合解決方案,涵蓋Pandas、Matplotlib和Seaborn三大工具的使用技巧,文中的示例代碼講解詳細,感興趣的小伙伴可以了解下2026-02-02

