Elasticsearch 論壇實戰-使用copy_to定製組合field解決cross-fields搜尋弊端
技術標籤:DW-pandas
第四章 分組
分組依據的本質
在groupby中傳入相應列名構成的列表即可。例如,現想根據學校和性別進行分組,統計身高的均值就可以如下寫出:
df.groupby(['School', 'Gender'])['Height'].mean()
groupby的分組依據都是直接可以從列中按照名字獲取的,那如果想要通過一定的複雜邏輯來分組,例如根據學生體重是否超過總體均值來分組,同樣還是計算身高的均值。
首先應該先寫出分組條件:
condition = df.Weight > df.Weight.mean()
df.groupby(condition) ['Height'].mean()
out:
Weight
False 159.034646
True 172.705357
Name: Height, dtype: float64
練一練
請根據上下四分位數分割,將體重分為high、normal、low三組,統計身高的均值。
#從索引可以看出,其實最後產生的結果就是按照條件列表中元素的值(此處是True和False)來分組,下面用隨機傳入字母序列來驗證這一想法:
item = np.random.choice(list('abc'), df.shape[0])
df.groupby(item)['Height'].mean()
out:
a 164.407143
b 161.930508
c 163.355882
Name: Height, dtype: float64
#此處的索引就是原先item中的元素,如果傳入多個序列進入groupby,那麼最後分組的依據就是這兩個序列對應行的唯一組合:
df.groupby([condition, item])['Height'].mean()
out:
Weight
False a 159.822222
b 158.338636
c 159.082979
True a 172.660000
b 172.466667
c 172.919048
Name: Height, dtype: float64
Groupby物件
最終具體做分組操作時,所呼叫的方法都來自於pandas中的groupby物件
gb = df.groupby(['School', 'Grade'])
out:
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000024E9F837288>
內建聚合函式
定義在groupby物件的聚合函式,因為它的速度基本都會經過內部的優化,使用功能時應當優先考慮。根據返回標量值的原則,包括如下函式:max/min/mean/median/count/all/any/idxmax/idxmin/mad/nunique/skew/quantile/sum/std/var/sem/size/prod。
gb = df.groupby('Gender')['Height']
gb.idxmin()
out:
Gender
Female 143
Male 199
Name: Height, dtype: int64
gb.quantile(0.95)
out:
Gender
Female 166.8
Male 185.9
Name: Height, dtype: float64
變換和過濾
變換函式與transform方法
變換函式的返回值為同長度的序列,最常用的內建變換函式是累計函式:cumcount/cumsum/cumprod/cummax/cummin,它們的使用方式和聚合函式類似,只不過完成的是組內累計操作。此外在groupby物件上還定義了填充類和滑窗類的變換函式。
gb.cummax().head()
out:
Height Weight
0 158.9 46.0
1 166.5 70.0
2 188.9 89.0
3 NaN 46.0
4 188.9 89.0
練一練
在groupby
物件中,rank
方法也是一個實用的變換函式,請查閱它的功能並給出一個使用的例子。
#現對身高和體重進行分組標準化,即減去組均值後除以組的標準差:
gb.transform(lambda x: (x-x.mean())/x.std()).head()
out:
Height Weight
0 -0.058760 -0.354888
1 -1.010925 -0.355000
2 2.167063 2.089498
3 NaN -1.279789
4 0.053133 0.159631
組索引與過濾
過濾在分組中是對於組的過濾,而索引是對於行的過濾,在第二章中的返回值,無論是布林列表還是元素列表或者位置列表,本質上都是對於行的篩選,即如果篩選條件的則選入結果的表,否則不選入。
組過濾作為行過濾的推廣,指的是如果對一個組的全體所在行進行統計的結果返回True則會被保留,False則該組會被過濾,最後把所有未被過濾的組其對應的所在行拼接起來作為DataFrame返回。
在groupby物件中,定義了filter方法進行組的篩選,其中自定義函式的輸入引數為資料來源構成的DataFrame本身,在之前例子中定義的groupby物件中,傳入的就是df[[‘Height’, ‘Weight’]],因此所有表方法和屬性都可以在自定義函式中相應地使用,同時只需保證自定義函式的返回為布林值即可。
# 例如,在原表中通過過濾得到所有容量大於100的組:
gb.filter(lambda x: x.shape[0] > 100).head()
out:
Height Weight
0 158.9 46.0
3 NaN 41.0
5 158.0 51.0
6 162.5 52.0
7 161.9 50.0