1. groupby技術
groupby 是pandas 中非常重要的一個函數, 主要用於數據聚合和分類計算. 其思想是“split-apply-combine”(拆分 - 應用 - 合併).
pandas groupby 的應用非常靈活, 但只要記住上面的核心思想-“split-apply-combine”, 就不難理解了. 我不太擅長解釋這類概念性的東西, 直接看例子吧.
2. 例子
美國有一個數據是關於職業調查的. 可以通過下面的鏈接下載.
數據.
數據很簡單, 稍微解釋一下.
user_id age gender occupation zip_code
1 24 M technician 85711
2 53 F other 94043
3 23 M writer 32067
4 24 M technician 43537
5 33 F other 15213
user_id: id號
age: 年齡
gender: 性別
occupation: 職業
zip_code: 郵政編碼, 通過郵政編碼可獲取所在城市
假設你已經下載並導入了上面的數據; 或者不需要下載, 直接用下面的代碼讀取遠程的數據.
url = "https://raw.githubusercontent.com/justmarkham/DAT8/master/data/u.user"
df = pd.read_csv(url, sep="|")
那麼, 怎麼解決下面的問題呢?
- 如何找出每一種職業的平均年齡?並按照平均年齡從大到小排序?
- 分別找出男人和女人每種職業的人數?
- 更進一步, 如何找出男人和女人在不同職業的平均年齡?
如果能快速解決上面的三個問題, 說明初步掌握groupby. 使用pandas解決的方法可能有多種, 但是這裏使用groupby還是比較方便的.
問題1 : 如何找出每一種職業的平均年齡?並按照平均年齡從大到小排序?
# 問題1, 一行代碼即可搞定
df.groupby("occupation").age.mean().sort_values(ascending=False)
# output
occupation
retired 63.071429
doctor 43.571429
educator 42.010526
healthcare 41.562500
librarian 40.000000
administrator 38.746835
executive 38.718750
marketing 37.615385
lawyer 36.750000
engineer 36.388060
writer 36.311111
salesman 35.666667
scientist 35.548387
other 34.523810
technician 33.148148
programmer 33.121212
homemaker 32.571429
artist 31.392857
entertainment 29.222222
none 26.555556
student 22.081633
Name: age, dtype: float64
sort_value
是用來排序的. 主要看前面的 df.groupby("occupation").age.mean()
, 還記得前面說的groupby的思想嗎, “split-apply-combine”(拆分 - 應用 - 合併).
首先df按照每一種occupation拆分成多個部分, 然後分別計算每種occupation的age的平均值.然後合併成一個Dataframe或者Series.
值得注意的是, groupby之後是一個對象, 知道應用一個函數之後纔會變成一個Series或者Dataframe.
type(df.groupby("occupation"))
# output
pandas.core.groupby.groupby.DataFrameGroupBy
問題2 : 分別找出男人和女人每種職業的人數?
df.groupby(['occupation','gender']).size()
# Output
occupation gender
administrator F 36
M 43
artist F 13
M 15
doctor M 7
educator F 26
M 69
...
與前例稍微不同的是, 這次按照兩個column, occupation和gender來進行group. 然後通過size計算每個職業指定性別的人數.
問題3 : 如何找出男人和女人在不同職業的平均年齡?
df.groupby(['occupation','gender']).age.mean()
# Output
occupation gender
administrator F 40.638889
M 37.162791
artist F 30.307692
M 32.333333
doctor M 43.571429
educator F 39.115385
M 43.101449
engineer F 29.500000
M 36.600000
...
groupby 詳解
通過上面的例子, groupby 的基本應用應該已經講清, 總而言之記住核心思想. 接下來詳細的聊聊groupby的各種應用及細節.
首先來看看官方文檔的參數描述.
DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, observed=False, **kwargs)
最常用的參數其實只有兩個, by 跟 as_index, 其他的很少用到, 如果有需要用到的那就仔細閱讀官方文檔
by 就是我們上面用的, 可以是column, 但其實也可以是與df同行的Series.
as_index 是指是否將groupby的column作爲index, 默認是True
對groupby對象應用自定義函數
上面我們都是以pandas自帶的函數應用再group對象上的, 可不可以使用自定義的函數呢? 答案是可以的.先看下面的代碼
demo = df[:5]
demo.groupby("gender").apply(lambda x: print(x))
# output
user_id age gender occupation zip_code
1 2 53 F other 94043
4 5 33 F other 15213
user_id age gender occupation zip_code
1 2 53 F other 94043
4 5 33 F other 15213
user_id age gender occupation zip_code
0 1 24 M technician 85711
2 3 23 M writer 32067
3 4 24 M technician 43537
也就是說, 其實groupby之後的dataframe是按照不同的值區分的. 這樣我們就可以直接自定義函數來處理了. 如果你細心的話, 你會發現其中一個dataframe出現了兩次, 這是apply 的設計問題.詳情請看這裏:https://stackoverflow.com/questions/21390035/python-pandas-groupby-object-apply-method-duplicates-first-group
未完待續...