python處理數據的風騷操做[pandas 之 groupby&agg]

https://segmentfault.com/a/1190000012394176html

介紹

每隔一段時間我都會去學習、回顧一下python中的新函數、新操做。這對於你後面的工做是有必定好處的。
本文重點介紹了pandas中groupby、Grouper和agg函數的使用。這2個函數做用相似,都是對數據集中的一類屬性進行聚合操做,好比統計一個用戶在每月內的所有花銷,統計某個屬性的最大、最小、累和、平均等數值。python

其中,agg是pandas 0.20新引入的功能git

groupby && Grouper

首先,咱們從網上把數據下載下來,後面的操做都是基於這份數據的:github

import pandas as pd df = pd.read_excel("https://github.com/chris1610/pbpython/blob/master/data/sample-salesv3.xlsx?raw=True") df["date"] = pd.to_datetime(df['date']) df.head()

圖片描述
(圖片來自於jupyter notebook,強烈推薦使用它做爲python的交互工具)
segmentfault

下面,咱們統計'ext price'這個屬性在每月的累和(sum)值,resample 只有在index爲date類型的時候才能用:dom

df.set_index('date').resample('M')['ext price'].sum()
date
2014-01-31 185361.66 2014-02-28 146211.62 2014-03-31 203921.38 2014-04-30 174574.11 2014-05-31 165418.55 2014-06-30 174089.33 2014-07-31 191662.11 2014-08-31 153778.59 2014-09-30 168443.17 2014-10-31 171495.32 2014-11-30 119961.22 2014-12-31 163867.26 Freq: M, Name: ext price, dtype: float64

進一步的,咱們想知道每一個用戶每月的sum值,那麼就須要一個groupby了:函數

df.set_index('date').groupby('name')['ext price'].resample("M").sum()
name                             date      
Barton LLC                       2014-01-31 6177.57 2014-02-28 12218.03 2014-03-31 3513.53 2014-04-30 11474.20 2014-05-31 10220.17 2014-06-30 10463.73 2014-07-31 6750.48 2014-08-31 17541.46 2014-09-30 14053.61 2014-10-31 9351.68 2014-11-30 4901.14 2014-12-31 2772.90 Cronin, Oberbrunner and Spencer 2014-01-31 1141.75 2014-02-28 13976.26 2014-03-31 11691.62 2014-04-30 3685.44 2014-05-31 6760.11 2014-06-30 5379.67 2014-07-31 6020.30 2014-08-31 5399.58 2014-09-30 12693.74 2014-10-31 9324.37 2014-11-30 6021.11 2014-12-31 7640.60 Frami, Hills and Schmidt 2014-01-31 5112.34 2014-02-28 4124.53 2014-03-31 10397.44 2014-04-30 5036.18 2014-05-31 4097.87 2014-06-30 13192.19 ... Trantow-Barrows 2014-07-31 11987.34 2014-08-31 17251.65 2014-09-30 6992.48 2014-10-31 10064.27 2014-11-30 6550.10 2014-12-31 10124.23 White-Trantow 2014-01-31 13703.77 2014-02-28 11783.98 2014-03-31 8583.05 2014-04-30 19009.20 2014-05-31 5877.29 2014-06-30 14791.32 2014-07-31 10242.62 2014-08-31 12287.21 2014-09-30 5315.16 2014-10-31 19896.85 2014-11-30 9544.61 2014-12-31 4806.93 Will LLC 2014-01-31 20953.87 2014-02-28 13613.06 2014-03-31 9838.93 2014-04-30 6094.94 2014-05-31 11856.95 2014-06-30 2419.52 2014-07-31 11017.54 2014-08-31 1439.82 2014-09-30 4345.99 2014-10-31 7085.33 2014-11-30 3210.44 2014-12-31 12561.21 Name: ext price, Length: 240, dtype: float64

結果確定是對的,可是不夠完美。咱們可使用Grouper寫得更加簡潔:工具

# df.set_index('date').groupby('name')['ext price'].resample("M").sum() df.groupby(['name', pd.Grouper(key='date', freq='M')])['ext price'].sum()

結果和上面👆同樣,就不列出來了。
顯然,這種寫法多敲了不少次鍵盤,那麼它的好處是啥呢?
首先,邏輯上更加直接,當你敲代碼完成以上統計的時候,你首先想到的就是groupby操做,而set_index, resample好像不會立馬想到。想到了groupby這個'動做'以後,你就會緊接着想按照哪一個key來操做,此時
你只須要用字符串,或者Grouper把key定義好就好了。最後使用聚合函數,就獲得告終果。因此,從人類的
思考角度看,後者更容易記憶。post

另外,Grouper裏的freq能夠方便的改爲其餘週期參數(resample也能夠),好比:學習

# 按照年度,且截止到12月最後一天統計ext price的sum值 df.groupby(['name', pd.Grouper(key='date', freq='A-DEC')])['ext price'].sum()
name                             date      
Barton LLC                       2014-12-31 109438.50 Cronin, Oberbrunner and Spencer 2014-12-31 89734.55 Frami, Hills and Schmidt 2014-12-31 103569.59 Fritsch, Russel and Anderson 2014-12-31 112214.71 Halvorson, Crona and Champlin 2014-12-31 70004.36 Herman LLC 2014-12-31 82865.00 Jerde-Hilpert 2014-12-31 112591.43 Kassulke, Ondricka and Metz 2014-12-31 86451.07 Keeling LLC 2014-12-31 100934.30 Kiehn-Spinka 2014-12-31 99608.77 Koepp Ltd 2014-12-31 103660.54 Kuhn-Gusikowski 2014-12-31 91094.28 Kulas Inc 2014-12-31 137351.96 Pollich LLC 2014-12-31 87347.18 Purdy-Kunde 2014-12-31 77898.21 Sanford and Sons 2014-12-31 98822.98 Stokes LLC 2014-12-31 91535.92 Trantow-Barrows 2014-12-31 123381.38 White-Trantow 2014-12-31 135841.99 Will LLC 2014-12-31 104437.60 Name: ext price, dtype: float64

agg

從0.20.1開始,pandas引入了agg函數,它提供基於列的聚合操做。而groupby能夠看作是基於行,或者說index的聚合操做。

從實現上看,groupby返回的是一個DataFrameGroupBy結構,這個結構必須調用聚合函數(如sum)以後,纔會獲得結構爲Series的數據結果。
而agg是DataFrame的直接方法,返回的也是一個DataFrame。固然,不少功能用sum、mean等等也能夠實現。可是agg更加簡潔, 並且傳給它的函數能夠是字符串,也能夠自定義,參數是column對應的子DataFrame

舉個栗子🌰吧:

df[["ext price", "quantity", "unit price"]].agg(['sum', 'mean'])

圖片描述

怎麼樣,是否是比使用

df[["ext price", "quantity"]].sum() df['unit price'].mean()

簡潔多了?

上例中,你還能夠針對不一樣的列使用不一樣的聚合函數:

df.agg({'ext price': ['sum', 'mean'], 'quantity': ['sum', 'mean'], 'unit price': ['mean']})

圖片描述

另外,自定義函數怎麼用呢,也是so easy.
好比,我想統計sku中,購買次數最多的產品編號,能夠這樣作:

# 這裏的x是sku對應的column get_max = lambda x: x.value_counts(dropna=False).index[0] df.agg({'ext price': ['sum', 'mean'], 'quantity': ['sum', 'mean'], 'unit price': ['mean'], 'sku': [get_max]})

圖片描述

<lambda>看起來很不協調,把它去掉:

get_max = lambda x: x.value_counts(dropna=False).index[0] # python就是靈活啊。 get_max.__name__ = "most frequent" df.agg({'ext price': ['sum', 'mean'], 'quantity': ['sum', 'mean'], 'unit price': ['mean'], 'sku': [get_max]})

另外,還有一個小問題,那就是若是你但願輸出的列按照某個順序排列,可使用collections的OrderedDict:

get_max = lambda x: x.value_counts(dropna=False).index[0] get_max.__name__ = "most frequent" import collections agg_dict = { 'ext price': ['sum', 'mean'], 'quantity': ['sum', 'mean'], 'unit price': ['mean'], 'sku': [get_max]} # 按照列名的長度排序。 OrderedDict的順序是跟插入順序一致的 df.agg(collections.OrderedDict(sorted(agg_dict.items(), key = lambda x: len(x[0]))))

圖片描述

總結

Python random模塊

http://www.cnblogs.com/learnC/p/5981638.html

利用python進行數據分析之數據聚合和分組運算

https://www.cnblogs.com/splended/p/5278078.html

https://www.cnblogs.com/learnC/p/5967297.html

https://www.cnblogs.com/splended/p/5278078.html

標準差

https://baike.baidu.com/item/%E6%A0%87%E5%87%86%E5%B7%AE/1415772?fr=aladdin

python 標準差計算(std)

https://blog.csdn.net/Gooooa/article/details/78923469

Pandas透視表(pivot_table)詳解

https://blog.csdn.net/chencheng126/article/details/50119215

 

當數據中存在NaN缺失值時,咱們能夠用其餘數值替代NaN,主要用到了DataFrame.fillna()方法

DataFrame.fillna(0)

相關文章
相關標籤/搜索