1. groupby技術(shù)
groupby 是pandas 中非常重要的一個(gè)函數(shù), 主要用于數(shù)據(jù)聚合和分類計(jì)算. 其思想是“split-apply-combine”(拆分 - 應(yīng)用 - 合并).
pandas groupby 的應(yīng)用非常靈活, 但只要記住上面的核心思想-“split-apply-combine”, 就不難理解了. 我不太擅長解釋這類概念性的東西, 直接看例子吧.
2. 例子
美國有一個(gè)數(shù)據(jù)是關(guān)于職業(yè)調(diào)查的. 可以通過下面的鏈接下載.
數(shù)據(jù).
數(shù)據(jù)很簡單, 稍微解釋一下.
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: 職業(yè)
zip_code: 郵政編碼, 通過郵政編碼可獲取所在城市
假設(shè)你已經(jīng)下載并導(dǎo)入了上面的數(shù)據(jù); 或者不需要下載, 直接用下面的代碼讀取遠(yuǎn)程的數(shù)據(jù).
url = "https://raw.githubusercontent.com/justmarkham/DAT8/master/data/u.user"
df = pd.read_csv(url, sep="|")
那么, 怎么解決下面的問題呢?
- 如何找出每一種職業(yè)的平均年齡?并按照平均年齡從大到小排序?
- 分別找出男人和女人每種職業(yè)的人數(shù)?
- 更進(jìn)一步, 如何找出男人和女人在不同職業(yè)的平均年齡?
如果能快速解決上面的三個(gè)問題, 說明初步掌握groupby. 使用pandas解決的方法可能有多種, 但是這里使用groupby還是比較方便的.
問題1 : 如何找出每一種職業(yè)的平均年齡?并按照平均年齡從大到小排序?
# 問題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”(拆分 - 應(yīng)用 - 合并).
首先df按照每一種occupation拆分成多個(gè)部分, 然后分別計(jì)算每種occupation的age的平均值.然后合并成一個(gè)Dataframe或者Series.
值得注意的是, groupby之后是一個(gè)對象, 知道應(yīng)用一個(gè)函數(shù)之后才會(huì)變成一個(gè)Series或者Dataframe.
type(df.groupby("occupation"))
# output
pandas.core.groupby.groupby.DataFrameGroupBy
問題2 : 分別找出男人和女人每種職業(yè)的人數(shù)?
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
...
與前例稍微不同的是, 這次按照兩個(gè)column, occupation和gender來進(jìn)行g(shù)roup. 然后通過size計(jì)算每個(gè)職業(yè)指定性別的人數(shù).
問題3 : 如何找出男人和女人在不同職業(yè)的平均年齡?
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 的基本應(yīng)用應(yīng)該已經(jīng)講清, 總而言之記住核心思想. 接下來詳細(xì)的聊聊groupby的各種應(yīng)用及細(xì)節(jié).
首先來看看官方文檔的參數(shù)描述.
DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, observed=False, **kwargs)
最常用的參數(shù)其實(shí)只有兩個(gè), by 跟 as_index, 其他的很少用到, 如果有需要用到的那就仔細(xì)閱讀官方文檔
by 就是我們上面用的, 可以是column, 但其實(shí)也可以是與df同行的Series.
as_index 是指是否將groupby的column作為index, 默認(rèn)是True
對groupby對象應(yīng)用自定義函數(shù)
上面我們都是以pandas自帶的函數(shù)應(yīng)用再group對象上的, 可不可以使用自定義的函數(shù)呢? 答案是可以的.先看下面的代碼
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
也就是說, 其實(shí)groupby之后的dataframe是按照不同的值區(qū)分的. 這樣我們就可以直接自定義函數(shù)來處理了. 如果你細(xì)心的話, 你會(huì)發(fā)現(xiàn)其中一個(gè)dataframe出現(xiàn)了兩次, 這是apply 的設(shè)計(jì)問題.詳情請看這里:https://stackoverflow.com/questions/21390035/python-pandas-groupby-object-apply-method-duplicates-first-group
未完待續(xù)...