計(jì))
數(shù)據(jù)洗干凈了接下來干嘛當(dāng)然是分析。拿到一份月度賬單你腦子里大概率會(huì)冒出這些問題這個(gè)月我吃飯花了多少錢哪一類花得最多平均每筆消費(fèi)多少錢用微信和支付寶哪個(gè)花得多單筆最貴的是哪一筆這些問題的答案一個(gè)groupby基本全能搞定。它是 Pandas 里最核心、最常用的技能之一??梢哉f不會(huì) groupby 就等于不會(huì)用 Pandas 做分析。今天我們就拿著一份賬單數(shù)據(jù)一個(gè)問題一個(gè)問題來回答。先把數(shù)據(jù)擺出來為了方便演示我們?cè)煲环輦€(gè)人賬單數(shù)據(jù)。你跟著敲一遍效果最好。importpandasaspd data{日期:[2026-09-01,2026-09-02,2026-09-02,2026-09-03,2026-09-04,2026-09-05,2026-09-05,2026-09-06,2026-09-07,2026-09-08,2026-09-09,2026-09-10,2026-09-11,2026-09-12,2026-09-13],類別:[餐飲,交通,餐飲,購物,餐飲,交通,娛樂,購物,餐飲,通訊,餐飲,交通,購物,娛樂,餐飲],金額:[35.5,8,42,199,28,6,89,259,56,129,38,15,499,168,45],支付方式:[微信,支付寶,微信,信用卡,微信,支付寶,微信,信用卡,支付寶,信用卡,微信,微信,信用卡,支付寶,微信]}dfpd.DataFrame(data)print(df)一共15筆消費(fèi)有日期、類別、金額、支付方式四個(gè)字段。接下來我們用這份數(shù)據(jù)回答5個(gè)問題。問題1每個(gè)類別分別花了多少錢這是最經(jīng)典的分組求和問題。resultdf.groupby(類別)[金額].sum()print(result)輸出類別 娛樂 257.0 交通 29.0 餐飲 244.5 通訊 129.0 購物 957.0 Name: 金額, dtype: float64一目了然——購物花得最多957塊。這句代碼怎么理解拆成三部分看部分作用df.groupby(類別)按類別列把數(shù)據(jù)分成好幾組[金額]選擇要統(tǒng)計(jì)的列只看金額這一列.sum()對(duì)每組分別求和先分組 → 再選列 → 最后聚合。三步走邏輯很清晰。小細(xì)節(jié)返回的是什么上面的結(jié)果左邊是類別名稱右邊是金額。它不是普通的表格叫Series——一維的帶索引。如果你想要一個(gè)正經(jīng)的表格DataFrame加個(gè).reset_index()resultdf.groupby(類別)[金額].sum().reset_index()print(result)類別 金額 0 娛樂 257.0 1 交通 29.0 2 餐飲 244.5 3 通訊 129.0 4 購物 957.0列名清清楚楚看著更舒服。問題2哪一類花得最多排個(gè)序看看光知道各花了多少還不夠。誰最多、誰最少排一下就知道了。resultdf.groupby(類別)[金額].sum().reset_index()result_sortedresult.sort_values(金額,ascendingFalse)print(result_sorted)輸出類別 金額 4 購物 957.0 0 娛樂 257.0 2 餐飲 244.5 3 通訊 129.0 1 交通 29.0ascendingFalse從大到小排降序ascendingTrue從小到大排升序默認(rèn)值排完序一眼就看到——購物是大頭占了總支出的近六成。來個(gè) Top 3排序 head 組合就是經(jīng)典的 Top Ntop3result.sort_values(金額,ascendingFalse).head(3)print(top3)購物、娛樂、餐飲是花錢最多的前三名。問題3每類平均每筆花多少錢筆數(shù)呢光看總額不夠全面。比如餐飲總額244.5但可能吃了10頓交通總額29但可能只有3筆。單價(jià)完全不一樣。這就需要同時(shí)算好幾個(gè)指標(biāo)。用agg()resultdf.groupby(類別)[金額].agg(總金額sum,筆數(shù)count,平均金額mean).reset_index()print(result.sort_values(總金額,ascendingFalse))輸出類別 總金額 筆數(shù) 平均金額 4 購物 957.0 3 319.000000 0 娛樂 257.0 2 128.500000 2 餐飲 244.5 6 40.750000 3 通訊 129.0 1 129.000000 1 交通 29.0 3 9.666667一行代碼總額、筆數(shù)、平均值全出來了??梢钥吹讲惋嬰m然總金額排第三但筆數(shù)最多6筆平均每頓才40塊。購物就3筆但平均單筆300多——對(duì)比很直觀。agg()是我寫代碼時(shí)最常用的 groupby 搭配。不用分別跑好幾遍一次算完列名還能自己起成中文可讀性高。常用聚合函數(shù)sum求和、mean平均、count計(jì)數(shù)、max最大、min最小、std標(biāo)準(zhǔn)差。知道這幾個(gè)絕大多數(shù)場(chǎng)景都?jí)蛴昧?。問題4不同支付方式分別花了多少這個(gè)問題跟問題1是一樣的思路只是分組的列從類別換成了支付方式pay_spenddf.groupby(支付方式)[金額].agg(總金額sum,筆數(shù)count).reset_index()print(pay_spend.sort_values(總金額,ascendingFalse))支付方式 總金額 筆數(shù) 0 信用卡 1086.0 4 1 微信 292.5 7 2 支付寶 238.0 4信用卡占了大頭主要是購物那幾筆大額都走了信用卡。如果想同時(shí)按類別支付方式分組呢有時(shí)候你想知道——餐飲里微信花了多少、支付寶花了多少這就需要按兩個(gè)列分組resultdf.groupby([類別,支付方式])[金額].sum().reset_index()print(result.head(10))groupby傳一個(gè)列表進(jìn)去就行幾列都可以。結(jié)果會(huì)是一個(gè)長表格每一行是類別 支付方式的組合。如果組合太多看起來亂可以配合排序或者透視表來看——透視表我們后面導(dǎo)出報(bào)表那篇會(huì)講。問題5單筆最高消費(fèi)是哪一筆這個(gè)問題有點(diǎn)不一樣。不是求某個(gè)統(tǒng)計(jì)值而是想找到具體那一行數(shù)據(jù)。你可能想這么寫# 思路不對(duì)——這樣只能拿到最大金額不知道是哪一筆print(df.groupby(類別)[金額].max())這只能看到每類的最大值但看不到完整的消費(fèi)信息。正確姿勢(shì)用idxmax()找到最大值所在的行索引再用loc取整行。max_indexdf[金額].idxmax()max_rowdf.loc[max_index]print(單筆最高消費(fèi))print(max_row)輸出單筆最高消費(fèi) 日期 2026-09-11 類別 購物 金額 499.0 支付方式 信用卡 Name: 12, dtype: objectidxmax()返回最大值所在行的索引再用.loc取整行——完整信息全出來了。延伸一下想知道每個(gè)類別里最貴的那一筆先分組再用applynlargest。這個(gè)稍微進(jìn)階一點(diǎn)先知道有這么個(gè)東西等你需要的時(shí)候能想起來就行。真實(shí)運(yùn)行效果下面把這份賬單代碼在本地真實(shí)跑一遍5 個(gè)問題的輸出原樣貼出來。截圖從每類消費(fèi)合計(jì)、按金額降序排序、agg 一次算出總額/筆數(shù)/均值到按支付方式分組、再用 idxmax 定位出單筆最高那筆9-11 購物 499 元全部是代碼直接打印的真實(shí)結(jié)果。5個(gè)問題答完了捋一捋用一份賬單數(shù)據(jù)回答了5個(gè)問題用到的全是 groupby 相關(guān)的技能。匯總一下問題用什么每類花了多少groupby sum誰花得最多sort_values排序 head取Top N每類平均/筆數(shù)/總額agg()一次算多個(gè)按不同維度分組groupby換列就行多列傳列表單筆最高是哪筆idxmax()找索引 loc取行說到底就三步先分組再選列最后聚合。順序別亂邏輯就清晰。新手常見的3個(gè)坑最后說幾個(gè) groupby 新手最容易踩的坑提前避開???groupby 之后直接 sum()出來一堆列df.groupby(類別).sum()這樣寫會(huì)把所有數(shù)值列都求和。我們這份數(shù)據(jù)只有金額是數(shù)值列所以問題不大如果有好幾個(gè)數(shù)值列它會(huì)全部求和結(jié)果很亂。好習(xí)慣先選列再聚合寫完整df.groupby(類別)[金額].sum()坑2聚合后列名看不懂用sum()返回的列名還是金額用agg([sum, count])列名就是英文的 sum、count。時(shí)間長了自己都忘了啥意思。好習(xí)慣用 agg 的關(guān)鍵字參數(shù)方式自己起列名df.groupby(類別)[金額].agg(總金額sum,筆數(shù)count)代碼可讀性直接上一個(gè)臺(tái)階。坑3忘了 reset_index結(jié)果索引怪怪的groupby 默認(rèn)會(huì)把分組鍵類別名變成索引。如果你想要一個(gè)普通表格記得加.reset_index()。不然后面用列名篩選數(shù)據(jù)的時(shí)候你會(huì)發(fā)現(xiàn)類別這列怎么都找不到——它在索引里呢。寫在最后分組統(tǒng)計(jì)這事說白了就是把賬單按類別切開每堆各自算一筆。但這玩意兒真不需要背——拿自己的真實(shí)賬單練幾次就什么都會(huì)了。畢竟花的是自己的錢分析起來比練習(xí)題有動(dòng)力多了 下一篇我們講數(shù)據(jù)篩選——布爾索引、loc、條件組合教你怎么從幾萬條數(shù)據(jù)里精準(zhǔn)撈出來你想要的那幾條。梅雅達(dá)編程工作室 · Python數(shù)據(jù)實(shí)戰(zhàn)系列第8篇先分組、再選列、最后聚合——順序記住了groupby 就是數(shù)據(jù)分析里最順手的那把刀。