在數(shù)據(jù)分析中,常常有這樣的場景,需要對不同類別的數(shù)據(jù),分別進(jìn)行處理,然后再將處理之后的內(nèi)容合并,作為結(jié)果輸出。對于這樣的場景,就需要借助靈活的groupby功能來處理。 groupby的操作過程如下 - split, 第一步,根據(jù)某一個或者多個變量的組合,將輸入數(shù)據(jù)分成多個group
- apply, 第二步, 對每個group對應(yīng)的數(shù)據(jù)進(jìn)行處理
- combine, 第三步,將分組處理的結(jié)果合并起來,形成一個新的數(shù)據(jù)
圖示如下 上述例子在python中的實現(xiàn)過程如下 >>> import numpy as np >>> import pandas as pd >>> df = pd.DataFrame({'x':['a','a','b','b','c','c'],'y':[2,4,0,5,5,10]}) >>> df x y 0 a 2 1 a 4 2 b 0 3 b 5 4 c 5 5 c 10
>>> df.groupby('x').mean() y x a 3.0 b 2.5 c 7.5 上述代碼實現(xiàn)的是分組求均值的操作,通過groupby方法,首選根據(jù)x標(biāo)簽的內(nèi)容分為a,b,c3組,然后對每組求均值,最后將結(jié)果進(jìn)行合并。 groupby函數(shù)的返回值為為DataFrameGroupBy對象,有以下幾個基本屬性和方法 >>> grouped = df.groupby('x') >>> grouped <pandas.core.groupby.generic.DataFrameGroupBy object at 0x06E94FA0> # groups屬性,返回值為字典,key是分組的類別 >>> grouped.groups {'a': Int64Index([0, 1], dtype='int64'), 'b': Int64Index([2, 3], dtype='int64'), 'c': Int64Index([4, 5], dtype='int64')} # len函數(shù)可以獲得分組后的組別數(shù) >>> len(grouped.groups) 3 # get_group方法可以獲得每個group對應(yīng)的數(shù)據(jù)框 >>> grouped.get_group('a') x y 0 a 2 1 a 4 >>> grouped.get_group('b') x y 2 b 0 3 b 5
# 遍歷group >>> for name, group in grouped: ... print(name) ... print(group) ... a x y 0 a 2 1 a 4 b x y 2 b 0 3 b 5 c x y 4 c 5 5 c 10 pandas中的groupby實際上非常的靈活且強(qiáng)大,具體的操作技巧有以下幾種 分組的依據(jù)既可以是單個標(biāo)簽,也可以是多個標(biāo)簽的組合,示例如下 >>> df = pd.DataFrame({'id':[1, 2, 3, 4], ... 'class':['a','a','b','b'], ... 'sex':['male', 'female', 'male', 'female'], ... 'age':[26, 16, 28, 30], ... }) >>> >>> df id class sex age 0 1 a male 26 1 2 a female 16 2 3 b male 28 3 4 b female 30
# 單個列標(biāo)簽進(jìn)行分組 >>> df.groupby('class')
# 多個列標(biāo)簽的組合,用列表的形式聲明 >>> df.groupby(['class','sex'])
# 用行標(biāo)簽分組 >>> arrays = [['Falcon', 'Falcon', 'Parrot', 'Parrot'], ... ['Captive', 'Wild', 'Captive', 'Wild']] >>> index = pd.MultiIndex.from_arrays(arrays, names=('Animal', 'Type')) >>> df = pd.DataFrame({'Max Speed': [390., 350., 30., 20.]}, ... index=index) >>> df Max Speed Animal Type Falcon Captive 390.0 Wild 350.0 Parrot Captive 30.0 Wild 20.0
# 針對行標(biāo)簽為multiindex的情況,用level指定分組的標(biāo)簽 # 既可以是數(shù)字索引 >>> df.groupby(level=0).mean() Max Speed Animal Falcon 370.0 Parrot 25.0 # 也可以是name屬性 >>> df.groupby(level="Type").mean() Max Speed Type Captive 210.0 Wild 185.0 分組處理就是對每個分組進(jìn)行相同的操作,groupby的返回對象并不是一個DataFrame, 所以無法直接使用DataFrame的一些操作函數(shù)。 針對一些常用的功能,groupby提供了一些函數(shù)來直接操作DataFrameGroupBy對象, 比如統(tǒng)計個數(shù),求和,求均值等,示例如下 # 計算每個group的個數(shù) >>> df.groupby('x').count() # 計算每個group的個數(shù) >>> df.groupby('x').size() # 求和 >>> df.groupby('x').sum() # 求均值 >>> df.groupby('x').mean() # 求中位數(shù) >>> df.groupby('x').median() # 求方差 >>> df.groupby('x').var() # 求標(biāo)準(zhǔn)差 >>> df.groupby('x').std() # 求最小值 >>> df.groupby('x').min() # 求最大值 >>> df.groupby('x').max() 這里只是列舉了部分函數(shù),完整列表請參見API。通過aggregate方法則可以靈活的使用各種函數(shù),用法如下
>>> df = pd.DataFrame({'x':['a','a','b','b','c','c'],'y':[2,4,0,5,5,10]}) # 一次使用一個函數(shù)進(jìn)行處理 >>> df.groupby('x').aggregate(np.mean) y x a 3.0 b 2.5 c 7.5 # agg是aggregate的簡寫 >>> df.groupby('x').agg(np.mean) y x a 3.0 b 2.5 c 7.5 # 一次使用多種函數(shù)進(jìn)行處理 >>> df.groupby('x').agg([np.sum, np.mean]) y sum mean x a 6 3.0 b 5 2.5 c 15 7.5 # 自定義輸出的列標(biāo)簽 >>> df.groupby('x').agg([np.sum,np.mean]).rename(columns={'sum':'cus_sum','mean':'cus_mean'}) y cus_sum cus_mean x a 6 3.0 b 5 2.5 c 15 7.5
>>> df = pd.DataFrame({'x':['a','a','b','b','c','c'],'y':[2,4,0,5,5,10],'z':[4.0,2.1,3.5,4.2,3.8,4.7]}) >>> df x y z 0 a 2 4.0 1 a 4 2.1 2 b 0 3.5 3 b 5 4.2 4 c 5 3.8 5 c 10 4.7 # 同一列用不用函數(shù)進(jìn)行處理 >>> df.groupby('x').agg(min=('y', 'min'), max=('y', 'max')) min max x a 2 4 b 0 5 c 5 10 # 不同列用不同函數(shù)進(jìn)行處理 >>> df.groupby('x').agg(min=('y', 'min'), max=('z', 'max')) min max x a 2 4.0 b 0 4.2 c 5 4.7 # 不同列用不同函數(shù)進(jìn)行處理 >>> df.groupby('x').agg({'y':'mean','z':'sum'}) y z x a 3.0 6.1 b 2.5 7.7 c 7.5 8.5 3. 分組過濾 當(dāng)需要根據(jù)某種條件對group進(jìn)行過濾時,可以使用filter方法,用法如下 >>> df = pd.DataFrame({'x':['a','a','b','b','c','c'],'y':[2,4,0,5,5,10]}) >>> df x y 0 a 2 1 a 4 2 b 0 3 b 5 4 c 5 5 c 10
>>> df.groupby('x').filter(lambda x: x.mean() > 2.5) x y 0 a 2 1 a 4 4 c 5 5 c 10 4. 匯總數(shù)據(jù) transform方法返回一個和輸入的原始數(shù)據(jù)相同尺寸的數(shù)據(jù)框,常用于在原始數(shù)據(jù)框的基礎(chǔ)上增加新的一列分組統(tǒng)計數(shù)據(jù),用法如下 >>> df = pd.DataFrame({'x':['a','a','b','b','c','c'],'y':[2,4,0,5,5,10]}) >>> df x y 0 a 2 1 a 4 2 b 0 3 b 5 4 c 5 5 c 10
# 輸出結(jié)果的行數(shù)和輸入的原始數(shù)據(jù)框相同 # 內(nèi)容為分組統(tǒng)計的結(jié)果 >>> df.groupby('x').transform(lambda x:x.count()) y 0 2 1 2 2 2 3 2 4 2 5 2 # 通過索引操作符,在原始數(shù)據(jù)框的基礎(chǔ)上添加匯總列 >>> df['mean_size'] = df.groupby('x').transform(lambda x:x.count()) >>> df x y mean_size 0 a 2 2 1 a 4 2 2 b 0 2 3 b 5 2 4 c 5 2 5 c 10 2 5. apply apply相比agg, 更加的靈活,用法如下 >>> df = pd.DataFrame({'x':['a','a','b','b','c','c'],'y':[2,4,0,5,5,10]}) >>> df x y 0 a 2 1 a 4 2 b 0 3 b 5 4 c 5 5 c 10
>>> df.groupby('x').apply(lambda x:x.count()) x y x a 2 2 b 2 2 c 2 2
>>> df.groupby('x').apply(lambda x:x - x.count()) y 0 0 1 2 2 -2 3 3 4 3 5 8 pandas中的groupby功能非常的靈活強(qiáng)大,可以極大提高數(shù)據(jù)處理的效率。
|