第3章 Pandas 分組(使用pandas進行數據分析,從小白逆襲大神,你會了嗎?)

第3章 分組

import numpy as np
import pandas as pd
df = pd.read_csv('data/table.csv',index_col='ID')
df

在這裏插入圖片描述

一、SAC過程

1. 內涵

1.SAC指的是分組操作中的split-apply-combine過程
2.其中split指基於某一些規則,將數據拆成若干組,apply是指對每一組獨立地使用函
數,combine指將每一組的結果組合成某一類數據結構

2. apply過程

在該過程中,我們實際往往會遇到四類問題:
1.整合(Aggregation)——即分組計算統計量(如求均值、求每組元素個數)
2.變換(Transformation)——即分組對每個單元的數據進行操作(如元素標準化)
3.過濾(Filtration)——即按照某些規則篩選出一些組(如選出組內某一指標小於50的組)
綜合問題——即前面提及的三種問題的混合

二、groupby函數

1. 分組函數的基本內容:

(a)根據某一列分組

grouped_single = df.groupby('School')

經過groupby後會生成一個groupby對象,該對象本身不會返回任何東西,只有當相應的方法被調用纔會起作用

例如取出某一個組:

grouped_single.get_group('S_2').head()

在這裏插入圖片描述
(b)根據某幾列分組

grouped_mul = df.groupby(['School','Class'])
grouped_mul.get_group(('S_1','C_3'))

在這裏插入圖片描述
(c)組容量與組數

grouped_single.size()

在這裏插入圖片描述

grouped_mul.size()

在這裏插入圖片描述

grouped_single.ngroups

在這裏插入圖片描述

grouped_mul.ngroups

在這裏插入圖片描述
(d)組的遍歷

for name,group in grouped_single:
    print(name)
    display(group.head())

在這裏插入圖片描述
(e)level參數(用於多級索引)和axis參數

 df.set_index(['Gender','School']).groupby(level=1,axis=0).get_group('S_1')

在這裏插入圖片描述

2. groupby對象的特點

(a)查看所有可調用的方法
由此可見,groupby對象可以使用相當多的函數,靈活程度很高

print([attr for attr in dir(grouped_single) if not attr.startswith('_')])

在這裏插入圖片描述
(b)分組對象的head和first
對分組對象使用head函數,返回的是每個組的前幾行,而不是數據集前幾行

grouped_single.head(3)

在這裏插入圖片描述
first顯示的是以分組爲索引的每組的第一個分組信息

grouped_single.first()

在這裏插入圖片描述
(c)分組依據

對於groupby函數而言,分組的依據是非常自由的,只要是與數據框長度相同的列表即可,同時支持函數型分組

np.random.choice(['a','b','c'],df.shape[0])

在這裏插入圖片描述

df.groupby(np.random.choice(['a','b','c'],df.shape[0])).get_group('b').head()
#相當於將np.random.choice(['a','b','c'],df.shape[0])當做新的一列進行分組

在這裏插入圖片描述
從原理上說,我們可以看到利用函數時,傳入的對象就是索引,因此根據這一特性可以做一些複雜的操作

df[:5].groupby(lambda x:print(x)).head(0)

在這裏插入圖片描述
根據奇偶行分組

df.groupby(lambda x:'奇數行' if not df.index.get_loc(x)%2==1 else '偶數行').groups

在這裏插入圖片描述
如果是多層索引,那麼lambda表達式中的輸入就是元組,下面實現的功能爲查看兩所學校中男女生分別均分是否及格

注意:此處只是演示groupby的用法,實際操作不會這樣寫

math_score = df.set_index(['Gender','School'])['Math'].sort_index()
grouped_score = df.set_index(['Gender','School']).sort_index().groupby(lambda x:(x,'均分及格' if math_score[x].mean()>=60 else '均分不及格'))
for name,_ in grouped_score:
    print(name)

在這裏插入圖片描述
(d)groupby的[]操作
可以用[]選出groupby對象的某個或者某幾個列,上面的均分比較可以如下簡潔地寫出:

df.groupby(['Gender','School'])['Math'].mean()>=60

在這裏插入圖片描述
用列表可選出多個屬性列:

df.groupby(['Gender','School'])[['Math','Height']].mean()

在這裏插入圖片描述
(e)連續型變量分組

例如利用cut函數對數學成績分組:

bins = [0,40,60,80,90,100]
cuts = pd.cut(df['Math'],bins=bins) #可選label添加自定義標籤
df.groupby(cuts)['Math'].count()

在這裏插入圖片描述

三、聚合、過濾和變換

1. 聚合(Aggregation)

(a)常用聚合函數

所謂聚合就是把一堆數,變成一個標量,因此mean/sum/size/count/std/var/sem/describe/first/last/nth/min/max都是聚合函數

爲了熟悉操作,不妨驗證標準誤sem函數,它的計算公式是:\frac{組內標準差}{\sqrt{組容量}},下面進行驗證:

group_m = grouped_single['Math']
group_m.std().values/np.sqrt(group_m.count().values)== group_m.sem().values

在這裏插入圖片描述
(b)同時使用多個聚合函數

group_m.agg(['sum','mean','std'])

在這裏插入圖片描述
利用元組進行重命名

group_m.agg([('rename_sum','sum'),('rename_mean','mean')])

在這裏插入圖片描述
指定哪些函數作用哪些列

grouped_mul.agg({'Math':['mean','max'],'Height':'var'})

在這裏插入圖片描述
(c)使用自定義函數

grouped_single['Math'].agg(lambda x:print(x.head(),'間隔'))
#可以發現,agg函數的傳入是分組逐列進行的,有了這個特性就可以做許多事情

在這裏插入圖片描述
官方沒有提供極差計算的函數,但通過agg可以容易地實現組內極差計算

grouped_single['Math'].agg(lambda x:x.max()-x.min())

在這裏插入圖片描述
(d)利用NamedAgg函數進行多個聚合

注意:不支持lambda函數,但是可以使用外置的def函數

def R1(x):
    return x.max()-x.min()
def R2(x):
    return x.max()-x.median()
grouped_single['Math'].agg(min_score1=pd.NamedAgg(column='col1', aggfunc=R1),
                           max_score1=pd.NamedAgg(column='col2', aggfunc='max'),
                           range_score2=pd.NamedAgg(column='col3', aggfunc=R2)).head()

在這裏插入圖片描述
(e)帶參數的聚合函數

判斷是否組內數學分數至少有一個值在50-52之間:

def f(s,low,high):
    return s.between(low,high).max()
grouped_single['Math'].agg(f,50,52)

在這裏插入圖片描述
如果需要使用多個函數,並且其中至少有一個帶參數,則使用wrap技巧:

def f_test(s,low,high):
    return s.between(low,high).max()
def agg_f(f_mul,name,*args,**kwargs):
    def wrapper(x):
        return f_mul(x,*args,**kwargs)
    wrapper.__name__ = name
    return wrapper
new_f = agg_f(f_test,'at_least_one_in_50_52',50,52)
grouped_single['Math'].agg([new_f,'mean']).head()

在這裏插入圖片描述

2. 過濾(Filteration)

filter函數是用來篩選某些組的(務必記住結果是組的全體),因此傳入的值應當是布爾標量

grouped_single[['Math','Physics']].filter(lambda x:(x['Math']>32).all()).head()

在這裏插入圖片描述

3. 變換(Transformation)

(a)傳入對象

transform函數中傳入的對象是組內的列,並且返回值需要與列長完全一致

grouped_single[['Math','Height']].transform(lambda x:x-x.min()).head()

在這裏插入圖片描述
如果返回了標量值,那麼組內的所有元素會被廣播爲這個值

grouped_single[['Math','Height']].transform(lambda x:x.mean()).head()

在這裏插入圖片描述
(b)利用變換方法進行組內標準化

grouped_single[['Math','Height']].transform(lambda x:(x-x.mean())/x.std()).head()

在這裏插入圖片描述
(c)利用變換方法進行組內缺失值的均值填充

df_nan = df[['Math','School']].copy().reset_index()
df_nan.loc[np.random.randint(0,df.shape[0],25),['Math']]=np.nan
df_nan.head()

在這裏插入圖片描述

df_nan.groupby('School').transform(lambda x: x.fillna(x.mean())).join(df.reset_index()['School']).head()

在這裏插入圖片描述

四、apply函數

1. apply函數的靈活性

可能在所有的分組函數中,apply是應用最爲廣泛的,這得益於它的靈活性:

對於傳入值而言,從下面的打印內容可以看到是以分組的表傳入apply中:

df.groupby('School').apply(lambda x:print(x.head(1)))

在這裏插入圖片描述
apply函數的靈活性很大程度來源於其返回值的多樣性:

① 標量返回值

df[['School','Math','Height']].groupby('School').apply(lambda x:x.max())

在這裏插入圖片描述
② 列表返回值

df[['School','Math','Height']].groupby('School').apply(lambda x:x-x.min()).head()

在這裏插入圖片描述
③ 數據框返回值

df[['School','Math','Height']].groupby('School')\
    .apply(lambda x:pd.DataFrame({'col1':x['Math']-x['Math'].max(),
                                  'col2':x['Math']-x['Math'].min(),
                                  'col3':x['Height']-x['Height'].max(),
                                  'col4':x['Height']-x['Height'].min()})).head()

在這裏插入圖片描述

2. 用apply同時統計多個指標

此處可以藉助OrderedDict工具進行快捷的統計:

from collections import OrderedDict
def f(df):
    data = OrderedDict()
    data['M_sum'] = df['Math'].sum()
    data['W_var'] = df['Weight'].var()
    data['H_mean'] = df['Height'].mean()
    return pd.Series(data)
grouped_single.apply(f)

在這裏插入圖片描述
代碼和數據地址:https://github.com/XiangLinPro/pandas

所有巧合的是要麼是上天註定要麼是一個人偷偷的在努力。

公衆號,關注回覆【電子書】有驚喜,資源多多。

個人微信公衆號,專注於學習資源、筆記分享,歡迎關注。我們一起成長,一起學習。一直純真着,善良着,溫情地熱愛生活,,如果覺得有點用的話,請不要吝嗇你手中點讚的權力,謝謝我親愛的讀者朋友
五角錢的程序員,專注於學習資源、筆記分享。

The only person you need to compare yourself to is who you have been. The only person you need to be better than is who you are.
你需要跟自己比的唯一一個人,就是曾經的自己。你需要比一個人變得更好,那個人就是現在的你。

給大家推薦一個Github,上面非常非常多的乾貨,保證讓你滿意:https://github.com/XiangLinPro/IT_book

關於Datawhale

Datawhale是一個專注於數據科學與AI領域的開源組織,彙集了衆多領域院校和知名企業的優秀學習者,聚合了一羣有開源精神和探索精神的團隊成員。Datawhale以“for the learner,和學習者一起成長”爲願景,鼓勵真實地展現自我、開放包容、互信互助、敢於試錯和勇於擔當。同時Datawhale 用開源的理念去探索開源內容、開源學習和開源方案,賦能人才培養,助力人才成長,建立起人與人,人與知識,人與企業和人與未來的聯結。

The mature never ask about the past;
the wise never ask about the present
and the open-minded never ask about the future.

成熟的人不問過去,
聰明的人不問現在,
豁達的人不問未來。

2020年5月8日於重慶城口
好好學習,天天向上,終有所獲

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章