pandas分組聚合(agg,transform,apply)
在日常的數(shù)據(jù)分析中,經(jīng)常需要將數(shù)據(jù)根據(jù)某個(多個)字段劃分為不同的群體(group)進(jìn)行分析,如電商領(lǐng)域?qū)⑷珖目備N售額根據(jù)省份進(jìn)行劃分,分析各省銷售額的變化情況,社交領(lǐng)域?qū)⒂脩舾鶕?jù)畫像(性別、年齡)進(jìn)行細(xì)分,研究用戶的使用情況和偏好等。在Pandas中,上述的數(shù)據(jù)處理操作主要運(yùn)用groupby完成,這篇文章就介紹一下groupby的基本原理及對應(yīng)的agg、transform和apply操作。
1. groupby分組
為了后續(xù)圖解的方便,采用模擬生成的10個樣本數(shù)據(jù),代碼和數(shù)據(jù)如下:
import pandas as pd import numpy as np data = pd.DataFrame({ "company": ["A", "B", "C", "A", "B", "C", "A", "B", "A", "A"], "salary": [10000, 10000, 50000, 50000, 40000, 50000, 30000, 10000, 20000, 40000], "age": [25, 30, 35, 40, 45, 20, 25, 30, 30, 35] } ) print('data = \n', data)
上面代碼輸出如下:
data =
company salary age
0 A 10000 25
1 B 10000 30
2 C 50000 35
3 A 50000 40
4 B 40000 45
5 C 50000 20
6 A 30000 25
7 B 10000 30
8 A 20000 30
9 A 40000 35
1.1 單列分組
group = data.groupby("company") print('group = ', group) print('list(group) = \n', list(group)) for index, data in group: print('index = ', index) print('data = \n', data)
上面代碼輸出如下:
group = <pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000000001DA85E0>
list(group) =
[('A', company salary age
0 A 10000 25
3 A 50000 40
6 A 30000 25
8 A 20000 30
9 A 40000 35), ('B', company salary age
1 B 10000 30
4 B 40000 45
7 B 10000 30), ('C', company salary age
2 C 50000 35
5 C 50000 20)]
index = A
data =
company salary age
0 A 10000 25
3 A 50000 40
6 A 30000 25
8 A 20000 30
9 A 40000 35
index = B
data =
company salary age
1 B 10000 30
4 B 40000 45
7 B 10000 30
index = C
data =
company salary age
2 C 50000 35
5 C 50000 20
1.2 多列分組
df_gb = data.groupby(['company', 'salary']) for (index1, index2), data in df_gb: print((index1, index2)) print('data = \n', data)
上面代碼輸出如下:
('A', 10000)
data =
company salary age
0 A 10000 25
('A', 20000)
data =
company salary age
8 A 20000 30
('A', 30000)
data =
company salary age
6 A 30000 25
('A', 40000)
data =
company salary age
9 A 40000 35
('A', 50000)
data =
company salary age
3 A 50000 40
('B', 10000)
data =
company salary age
1 B 10000 30
7 B 10000 30
('B', 40000)
data =
company salary age
4 B 40000 45
('C', 50000)
data =
company salary age
2 C 50000 35
5 C 50000 20
1.3 groupby的基本原理
在pandas中,實(shí)現(xiàn)分組操作的代碼很簡單,僅需一行代碼,在這里,將上面的數(shù)據(jù)集按照company字段進(jìn)行劃分
group = data.groupby(“company”)
會得到一個DataFrameGroupBy對象,那這個生成的DataFrameGroupBy是啥呢?返回的結(jié)果是其內(nèi)存地址,并不利于直觀地理解,為了看看group內(nèi)部究竟是什么,這里把group轉(zhuǎn)換成list的形式來看。或者for循環(huán)迭代出來看。
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000002B7E2650240>
轉(zhuǎn)換成列表的形式后,可以看到,列表由三個元組組成,每個元組中,第一個元素是組別(這里是按照company進(jìn)行分組,所以最后分為了A,B,C),第二個元素的是對應(yīng)組別下的DataFrame,整個過程可以圖解如下:
總結(jié)來說,groupby的過程就是將原有的DataFrame按照groupby的字段(這里是company),劃分為若干個分組DataFrame,被分為多少個組就有多少個分組DataFrame。所以說,在groupby之后的一系列操作(如agg、apply等),均是基于子DataFrame的操作。理解了這點(diǎn),也就基本摸清了Pandas中g(shù)roupby操作的主要原理。下面來講講groupby之后的常見操作。
2. groupby|agg聚合
聚合操作是groupby后非常常見的操作,會寫SQL的朋友對此應(yīng)該是非常熟悉了。聚合操作可以用來求和、均值、最大值、最小值等,下面的表格列出了Pandas中常見的聚合操作。
2.1 對分組后所有數(shù)據(jù)進(jìn)行聚合
默認(rèn)情況對分組之后其他列進(jìn)行聚合
df_agg = data.groupby('company').agg(['min', 'mean', 'max']) print(df_agg)
上面代碼輸出如下:
salary age
min mean max min mean max
company
A 10000 30000 50000 25 31.0 40
B 10000 20000 40000 30 35.0 45
C 50000 50000 50000 20 27.5 35
2.2 對分組后的部分列進(jìn)行聚合
某些情況,只需要對部分?jǐn)?shù)據(jù)進(jìn)行不同的聚合操作,可以通過字典來構(gòu)建
print(data.groupby('company').agg({'age': ['min', 'mean', 'max']}))
上面代碼輸出如下:
age
min mean max
company
A 25 31.0 40
B 30 35.0 45
C 20 27.5 35
age salary
print(data.groupby('company').agg({'age': ['min', 'mean', 'max'], 'salary': 'min'}))
上面代碼輸出如下:
age salary
min mean max min
company
A 25 31.0 40 10000
B 30 35.0 45 10000
C 20 27.5 35 50000
print(data.groupby('company').agg({'salary': 'median', 'age': 'mean'}))
上面代碼輸出如下:
salary age
company
A 30000 31.0
B 10000 35.0
C 50000 27.5
2.3 agg聚合過程圖解
3. groupby|transform
transform是一種什么數(shù)據(jù)操作?和agg有什么區(qū)別呢?為了更好地理解transform和agg的不同,下面從實(shí)際的應(yīng)用場景出發(fā)進(jìn)行對比。
在上面的agg中,我們學(xué)會了如何求不同公司員工的平均薪水,如果現(xiàn)在需要在原數(shù)據(jù)集中新增一列avg_salary,代表員工所在的公司的平均薪水(相同公司的員工具有一樣的平均薪水),該怎么實(shí)現(xiàn)呢?如果按照正常的步驟來計算,需要先求得不同公司的平均薪水,然后按照員工和公司的對應(yīng)關(guān)系填充到對應(yīng)的位置,不用transform的話,實(shí)現(xiàn)代碼如下:
avg_salary_dict = data.groupby('company')['salary'].mean().to_dict() data['avg_salary'] = data['company'].map(avg_salary_dict) print('data = \n', data)
上面代碼輸出如下:
data =
company salary age avg_salary
0 A 10000 25 30000
1 B 10000 30 20000
2 C 50000 35 50000
3 A 50000 40 30000
4 B 40000 45 20000
5 C 50000 20 50000
6 A 30000 25 30000
7 B 10000 30 20000
8 A 20000 30 30000
9 A 40000 35 30000
如果使用transform的話,僅需要一行代碼:
data['avg_salary'] = data.groupby('company')['salary'].transform('mean') print('data = \n', data)
上面代碼輸出如下:
data =
company salary age avg_salary
0 A 10000 25 30000
1 B 10000 30 20000
2 C 50000 35 50000
3 A 50000 40 30000
4 B 40000 45 20000
5 C 50000 20 50000
6 A 30000 25 30000
7 B 10000 30 20000
8 A 20000 30 30000
9 A 40000 35 30000
3.1 transform實(shí)現(xiàn)過程圖解
還是以圖解的方式來看看進(jìn)行g(shù)roupby后transform的實(shí)現(xiàn)過程(為了更直觀展示,圖中加入了company列,實(shí)際按照上面的代碼只有salary列):
圖中的大方框是transform和agg所不一樣的地方,對agg而言,會計算得到A,B,C公司對應(yīng)的均值并直接返回,但對transform而言,則會對每一條數(shù)據(jù)求得相應(yīng)的結(jié)果,同一組內(nèi)的樣本會有相同的值,組內(nèi)求完均值后會按照原索引的順序返回結(jié)果,如果有不理解的可以拿這張圖和agg那張對比一下。
4. groupby|apply
apply應(yīng)該是大家的老朋友了,它相比agg和transform而言更加靈活,能夠傳入任意自定義的函數(shù),實(shí)現(xiàn)復(fù)雜的數(shù)據(jù)操作。在Pandas數(shù)據(jù)處理三板斧——map、apply、applymap詳解中,介紹了apply的使用,那在groupby后使用apply和之前所介紹的有什么區(qū)別呢?
區(qū)別是有的,但是整個實(shí)現(xiàn)原理是基本一致的。兩者的區(qū)別在于,對于groupby后的apply,以分組后的子DataFrame作為參數(shù)傳入指定函數(shù)的,基本操作單位是DataFrame,而之前介紹的apply的基本操作單位是Series。還是以一個案例來介紹groupby后的apply用法。
假設(shè)我現(xiàn)在需要獲取各個公司年齡最大的員工的數(shù)據(jù),該怎么實(shí)現(xiàn)呢?可以用以下代碼實(shí)現(xiàn):
def get_oldest_staff(x): df = x.sort_values(by= 'age', ascending = True) return df.iloc[-1, :] oldest_staff = data.groupby('company', as_index = False).apply(get_oldest_staff) print('oldest_staff = \n', oldest_staff)
上面代碼輸出如下:
oldest_staff =
company salary age
0 A 50000 40
1 B 40000 45
2 C 50000 35
流程圖如下:
可以看到,此處的apply和上篇文章中所介紹的作用原理基本一致,只是傳入函數(shù)的參數(shù)由Series變?yōu)榱舜颂幍姆纸MDataFrame。
最后,關(guān)于apply的使用,這里有個小建議,雖然說apply擁有更大的靈活性,但apply的運(yùn)行效率會比agg和transform更慢。所以,groupby之后能用agg和transform解決的問題還是優(yōu)先使用這兩個方法,實(shí)在解決不了了才考慮使用apply進(jìn)行操作。
到此這篇關(guān)于pandas分組聚合(agg,transform,apply)的文章就介紹到這了,更多相關(guān)pandas分組聚合內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python實(shí)現(xiàn)http接口自動化測試的示例代碼
這篇文章主要介紹了Python實(shí)現(xiàn)http接口自動化測試的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10python雙向鏈表實(shí)現(xiàn)實(shí)例代碼
python雙向鏈表和單鏈表類似,只不過是增加了一個指向前面一個元素的指針,下面的代碼實(shí)例了python雙向鏈表的方法2013-11-11python將txt等文件中的數(shù)據(jù)讀為numpy數(shù)組的方法
今天小編就為大家分享一篇python將txt等文件中的數(shù)據(jù)讀為numpy數(shù)組的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-12-12Python實(shí)現(xiàn)vlog生成器的示例代碼
vlog,全稱為Video?blog,意為影音博客,也有翻譯為微錄。本文將嘗試用Python基于Moviepy從一個文本文件中自動生成一個視頻格式的vlog,感興趣的可以了解一下2023-01-01python3將變量寫入SQL語句的實(shí)現(xiàn)方式
這篇文章主要介紹了python3將變量寫入SQL語句的實(shí)現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03Python實(shí)現(xiàn)批量設(shè)置圖片背景為透明
我們?nèi)粘I钪兄谱鱌PT等教學(xué)資源時,需要批量去除圖片背景,就可以使用 Python 的 rembg 庫,下面我們就來看看如何操作rembg實(shí)現(xiàn)批量設(shè)置圖片背景為透明吧2024-11-11