文章目錄
- 使用內置統計方法聚合數據
- 面向列的聚合方法
- aggregate()方法
- 對每一列數據應用同一個函數
- 對某列數據應用不同的函數
- 對不同列數據應用不同函數
使用內置統計方法聚合數據
實現數據拆分成組并分別計算平均數的操作
代碼:
import pandas as pd
import numpy as npdf = pd.DataFrame({'key1': ['A', 'A', 'B', 'B', 'A'],'key2': ['one', 'two', 'one', 'two', 'one'],'data1': [2, 3, 4, 6, 8],'data2': [3, 5, np.nan, 3, 7]})
print(df.groupby('key1').mean())
輸出結果:
data1 data2
key1
A 4.333333 5.0
B 5.000000 3.0
可以看到的是,如果參與運算的數據中有NaN值,會自動將這些NaN值過濾掉
面向列的聚合方法
當內置方法無法滿足聚合要求時,可以自定義一個函數,將它傳給agg()方法(pandas 0.20版本后,aggregate()方法與agg()方法用法一樣)。
aggregate()方法
aggregate(self, func=None, *args, **kwargs)
上述方法中部分參數表示的含義如下:
- func:表示用于匯總數據的函數,可以為單個函數或函數列表
- axis:表示函數作用于軸的方向,0或1,index或columns
通過aggregate()方法進行聚合時,func參數既可以接受Pandas中的內置方法,也可以接受自定義的函數,同時,這些方法與函數可以作用于每一列,也可以將多個函數或方法作用于同一列,還可以將不同函數或方法作用于不同的列。
對每一列數據應用同一個函數
創建測試對象:
df1 = DataFrame(np.arange(36).reshape(6, 6),columns=list('abcdef'))
df1['key'] = Series(list('aaabbb'), name='key')
print(df1)
輸出結果:
a b c d e f key
0 0 1 2 3 4 5 a
1 6 7 8 9 10 11 a
2 12 13 14 15 16 17 a
3 18 19 20 21 22 23 b
4 24 25 26 27 28 29 b
5 30 31 32 33 34 35 b
接下來對測試對象以“key“列為分組鍵進行拆分,并通過字典的形式分別打印出每個分組的具體內容。
進行拆分
df1_group = df1.groupby(by='key')
print(dict([i for i in df1_group])['a'])
print(dict([i for i in df1_group])['b'])
輸出結果:
a b c d e f key
0 0 1 2 3 4 5 a
1 6 7 8 9 10 11 a
2 12 13 14 15 16 17 aa b c d e f key
3 18 19 20 21 22 23 b
4 24 25 26 27 28 29 b
5 30 31 32 33 34 35 b
上述過程中,先調用groupby()方法,按key一列的數據將df1對象進行分為a、b兩組,然后使用列表推導式([i for i in df1_group])遍歷分組對象df1_group,得到每個分組的列表,之后將裝有分組的列表強轉換為字典,其中字典中的鍵為a和b,字典的值分別為分組的具體內容。之后通過“字典[組名]”的形式,分別查看a、b組數據。
當然也可以用for循環直接兩組一起輸出
for i in df1_group:print(i)
輸出結果
('a', a b c d e f key
0 0 1 2 3 4 5 a
1 6 7 8 9 10 11 a
2 12 13 14 15 16 17 a)
('b', a b c d e f key
3 18 19 20 21 22 23 b
4 24 25 26 27 28 29 b
5 30 31 32 33 34 35 b)
接下來,對每個分組的數據進行聚合運算。
調用內置的求和方法sum():
print("sum:\n", df1_group.aggregate(sum))
輸出結果:
sum:a b c d e f
key
a 18 21 24 27 30 33
b 72 75 78 81 84 87
自定義一個實現求極差值(極差值 = 最大值 - 最小值)的函數,然后將其作為參數傳入aggregate()方法中:
def range_df1_group(arr):return arr.max() - arr.min()print("極差值:\n", df1_group.aggregate(range_df1_group))
輸出結果:
極差值:a b c d e f
key
a 12 12 12 12 12 12
b 12 12 12 12 12 12
對某列數據應用不同的函數
如今要求不僅要求出每組數據的極差,還要計算出每組數據的和。這是可將兩個函數的名稱放在列表中,之后在調用aggregate()方法聚合時作為參數傳入即可。
代碼實現:
print("sum and 極差值:\n", df1_group.aggregate(func=[sum, range_df1_group]))
輸出結果:
sum and 極差值:a b ... e f sum range_df1_group sum ... range_df1_group sum range_df1_group
key ...
a 18 12 21 ... 12 33 12
b 72 12 75 ... 12 87 12[2 rows x 12 columns]
從輸出結果可以看出,生成的DataFrame對象具有兩層索引,每個外層列索引包含兩個內層列索引,分別以函數的名稱range_df1_group和sum命名。
雖然每一列可以應用不同的函數,但是結果并不能很直觀地辨別出每個函數代表的意義。為了更好地反映出每列對應地數據的信息, 可以使用“(name,function)”元組將function(函數名)替換為name(自定義名稱)。
代碼實現:
print("極差值 and sum:\n",
df1_group.aggregate([("極差", range_df1_group), ("和", sum)]))
輸出結果:
極差值 and sum:a b c d e f 極差 和 極差 和 極差 和 極差 和 極差 和 極差 和
key
a 12 18 12 21 12 24 12 27 12 30 12 33
b 12 72 12 75 12 78 12 81 12 84 12 87
區別其實就是不會出現列名過長導致的無法顯示全的問題了
對不同列數據應用不同函數
如果希望實現對不同列數據應用不同函數,咋可以在aggregate()方法中傳入一個{“列名”:“函數名”}格式的字典。
代碼實現:
print("綜合:\n",
df1_group.aggregate({'a': 'sum', 'b': range_df1_group, 'c': 'mean'})
輸出結果:
綜合:a b c
key
a 18 12 8
b 72 12 26
上例中,使用不同的函數對每個分組執行聚合運算,其中a列執行求和運算,b列執行求極差計算,c列執行求平均值計算。自定義函數不需要加引號。
aggregate()方法執行聚合操作時,會將一組標量值參與某些運算后轉換為一個標量值。