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