玩转 Pandas 的 Groupby 操作
作者:Lemon
來源:Python數(shù)據(jù)之道
玩轉(zhuǎn) Pandas 的 Groupby 操作
大家好,我是 Lemon,今天來跟大家分享下 pandas 中 groupby 的用法。
Pandas 的 groupby() 功能很強大,用好了可以方便的解決很多問題,在數(shù)據(jù)處理以及日常工作中經(jīng)常能施展拳腳。
今天,我們一起來領(lǐng)略下 groupby() 的魅力吧。
首先,引入相關(guān) package :
import?pandas?as?pd import?numpy?as?npgroupby 的基礎(chǔ)操作
經(jīng)常用 groupby 對 pandas 中 dataframe 的各列進行統(tǒng)計,包括求和、求均值等。
In?[2]:?df?=?pd.DataFrame({'A':?['a',?'b',?'a',?'c',?'a',?'c',?'b',?'c'],?...:????????????????????'B':?[2,?8,?1,?4,?3,?2,?5,?9],?...:????????????????????'C':?[102,?98,?107,?104,?115,?87,?92,?123]})...:?df...:?Out[2]:?A??B????C 0??a??2??102 1??b??8???98 2??a??1??107 3??c??4??104 4??a??3??115 5??c??2???87 6??b??5???92 7??c??9??123按 A 列分組(groupby),獲取其他列的均值
df.groupby('A').mean()Out[3]:?B???????????C A????????????????? a??2.0??108.000000 b??6.5???95.000000 c??5.0??104.666667按多列進行分組(groupby)
df.groupby(['A','B']).mean()Out[4]:?C A?B????? a?1??1072??1023??115 b?5???928???98 c?2???874??1049??123分組后選擇列進行運算
分組后,可以選取單列數(shù)據(jù),或者多個列組成的列表(list)進行運算
In?[5]:?df?=?pd.DataFrame([[1,?1,?2],?[1,?2,?3],?[2,?3,?4]],?columns=["A",?"B",?"C"])...:?df...:?Out[5]:?A??B??C 0??1??1??2 1??1??2??3 2??2??3??4In?[6]:?g?=?df.groupby("A")In?[7]:?g['B'].mean()?#?僅選擇B列Out[7]:? A 1????1.5 2????3.0 Name:?B,?dtype:?float64In?[8]:?g[['B',?'C']].mean()?#?選擇B、C列Out[8]:?B????C A?????????? 1??1.5??2.5 2??3.0??4.0可以針對不同的列選用不同的聚合方法
In?[9]:?g.agg({'B':'mean',?'C':'sum'})Out[9]:?B??C A???????? 1??1.5??5 2??3.0??4聚合方法
聚合方法有 size() 和 count() 。
size 跟 count 的區(qū)別:size 計數(shù)時包含 NaN 值,而 count 不包含 NaN值
In?[10]:?df?=?pd.DataFrame({"Name":["Alice",?"Bob",?"Mallory",?"Mallory",?"Bob"?,?"Mallory"],...:??????????????????"City":["Seattle",?"Seattle",?"Portland",?"Seattle",?"Seattle",?"Portland"],...:??????????????????"Val":[4,3,3,np.nan,np.nan,4]})...:?...:?df...:? Out[10]:?City?????Name??Val 0???Seattle????Alice??4.0 1???Seattle??????Bob??3.0 2??Portland??Mallory??3.0 3???Seattle??Mallory??NaN 4???Seattle??????Bob??NaN 5??Portland??Mallory??4.0count()
In?[11]:?df.groupby(["Name",?"City"],?as_index=False)['Val'].count()Out[11]:?Name??????City??Val 0????Alice???Seattle????1 1??????Bob???Seattle????1 2??Mallory??Portland????2 3??Mallory???Seattle????0size()
In?[12]:?df.groupby(["Name",?"City"])['Val'].size().reset_index(name='Size')Out[12]:?Name??????City??Size 0????Alice???Seattle?????1 1??????Bob???Seattle?????2 2??Mallory??Portland?????2 3??Mallory???Seattle?????1分組運算方法 agg()
針對某列使用agg()時進行不同的統(tǒng)計運算
In?[13]:?df?=?pd.DataFrame({'A':?list('XYZXYZXYZX'),?'B':?[1,?2,?1,?3,?1,?2,?3,?3,?1,?2],?...:????????????????????????????'C':?[12,?14,?11,?12,?13,?14,?16,?12,?10,?19]})...:?df...:? Out[13]:?A??B???C 0??X??1??12 1??Y??2??14 2??Z??1??11 3??X??3??12 4??Y??1??13 5??Z??2??14 6??X??3??16 7??Y??3??12 8??Z??1??10 9??X??2??19In?[14]:?df.groupby('A')['B'].agg({'mean':np.mean,?'standard?deviation':?np.std})Out[14]:?mean??standard?deviation A?????????????????????????????? X??2.250000????????????0.957427 Y??2.000000????????????1.000000 Z??1.333333????????????0.577350針對不同的列應用多種不同的統(tǒng)計方法
In?[15]:?df.groupby('A').agg({'B':[np.mean,?'sum'],?'C':['count',np.std]})Out[15]:?B?????????C??????????mean?sum?count???????std A?????????????????????????????? X??2.250000???9?????4??3.403430 Y??2.000000???6?????3??1.000000 Z??1.333333???4?????3??2.081666分組運算方法 apply()
In?[16]:?df?=?pd.DataFrame({'A':?list('XYZXYZXYZX'),?'B':?[1,?2,?1,?3,?1,?2,?3,?3,?1,?2],?...:????????????????????????????'C':?[12,?14,?11,?12,?13,?14,?16,?12,?10,?19]})...:?df...:? Out[16]:?A??B???C 0??X??1??12 1??Y??2??14 2??Z??1??11 3??X??3??12 4??Y??1??13 5??Z??2??14 6??X??3??16 7??Y??3??12 8??Z??1??10 9??X??2??19In?[17]:?df.groupby('A').apply(np.mean)...:?#?跟下面的方法的運行結(jié)果是一致的...:?#?df.groupby('A').mean() Out[17]:?B??????????C A????????????????????? X??2.250000??14.750000 Y??2.000000??13.000000 Z??1.333333??11.666667apply() 方法可以應用 lambda 函數(shù),舉例如下:
In?[18]:?df.groupby('A').apply(lambda?x:?x['C']-x['B']) Out[18]:? A??? X??0????113?????96????139????17 Y??1????124????127?????9 Z??2????105????128?????9 dtype:?int64In?[19]:?df.groupby('A').apply(lambda?x:?(x['C']-x['B']).mean()) Out[19]:? A X????12.500000 Y????11.000000 Z????10.333333 dtype:?float64分組運算方法 transform()
前面進行聚合運算的時候,得到的結(jié)果是一個以分組名為 index 的結(jié)果對象。如果我們想使用原數(shù)組的 index 的話,就需要進行 merge 轉(zhuǎn)換。transform(func, *args, **kwargs) 方法簡化了這個過程,它會把 func 參數(shù)應用到所有分組,然后把結(jié)果放置到原數(shù)組的 index 上(如果結(jié)果是一個標量,就進行廣播):
In?[20]:?df?=?pd.DataFrame({'group1'?:??['A',?'A',?'A',?'A',...:????????????????????????????????'B',?'B',?'B',?'B'],...:????????????????????'group2'?:??['C',?'C',?'C',?'D',...:????????????????????????????????'E',?'E',?'F',?'F'],...:????????????????????'B'??????:??['one',?np.NaN,?np.NaN,?np.NaN,...:?????????????????????????????????np.NaN,?'two',?np.NaN,?np.NaN],...:????????????????????'C'??????:??[np.NaN,?1,?np.NaN,?np.NaN,...:????????????????????????????????np.NaN,?np.NaN,?np.NaN,?4]})???????????...:?df...:? Out[20]:?B????C?group1?group2 0??one??NaN??????A??????C 1??NaN??1.0??????A??????C 2??NaN??NaN??????A??????C 3??NaN??NaN??????A??????D 4??NaN??NaN??????B??????E 5??two??NaN??????B??????E 6??NaN??NaN??????B??????F 7??NaN??4.0??????B??????FIn?[21]:?df.groupby(['group1',?'group2'])['B'].transform('count') Out[21]:? 0????1 1????1 2????1 3????0 4????1 5????1 6????0 7????0 Name:?B,?dtype:?int64In?[22]:?df['count_B']=df.groupby(['group1',?'group2'])['B'].transform('count')...:?df...:? Out[22]:?B????C?group1?group2??count_B 0??one??NaN??????A??????C????????1 1??NaN??1.0??????A??????C????????1 2??NaN??NaN??????A??????C????????1 3??NaN??NaN??????A??????D????????0 4??NaN??NaN??????B??????E????????1 5??two??NaN??????B??????E????????1 6??NaN??NaN??????B??????F????????0 7??NaN??4.0??????B??????F????????0上面運算的結(jié)果分析:{'group1':'A', 'group2':'C'} 的組合共出現(xiàn)3次,即 index為 0,1,2。對應 "B" 列的值分別是 "one","NaN","NaN",由于 count() 計數(shù)時不包括NaN值,因此 {'group1':'A', 'group2':'C'} 的 count 計數(shù)值為 1 。
transform() 方法會將該計數(shù)值在 dataframe 中所有涉及的 rows 都顯示出來(我理解應該就進行廣播)
將某列數(shù)據(jù)按數(shù)據(jù)值分成不同范圍段進行分組(groupby)運算
In?[23]:?np.random.seed(0)...:?df?=?pd.DataFrame({'Age':?np.random.randint(20,?70,?100),?...:????????????????????'Sex':?np.random.choice(['Male',?'Female'],?100),?...:????????????????????'number_of_foo':?np.random.randint(1,?20,?100)})...:?df.head()...:? Out[23]:?Age?????Sex??number_of_foo 0???64??Female?????????????14 1???67??Female?????????????14 2???20??Female?????????????12 3???23????Male?????????????17 4???23??Female?????????????15這里將 “Age” 列分成三類,有兩種方法可以實現(xiàn):
(a)bins=4
(b)bins=[19, 40, 65, np.inf]
In?[24]:?pd.cut(df['Age'],?bins=4) Out[24]:? ...In?[25]:?pd.cut(df['Age'],?bins=[19,40,65,np.inf])分組結(jié)果范圍結(jié)果如下:
In?[26]:?age_groups?=?pd.cut(df['Age'],?bins=[19,40,65,np.inf])...:?df.groupby(age_groups).mean()運行結(jié)果如下:
按‘Age’分組范圍和性別(sex)進行制作交叉表
In?[27]:?pd.crosstab(age_groups,?df['Sex'])運行結(jié)果如下:
往期推薦: 收藏 | 49 個 Python 學習資源我都逛哪些技術(shù)網(wǎng)站?(程序員必備58個網(wǎng)站匯總)肝!精心整理了 50 個數(shù)據(jù)源網(wǎng)站!????分享、點贊、在看,給個三連擊唄!?????
總結(jié)
以上是生活随笔為你收集整理的玩转 Pandas 的 Groupby 操作的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 送一台自用笔记本电脑!新款
- 下一篇: GitHub上3天1W赞的程序员学习路线