pandas中的agg&transform方法
1 聚合函數 agg
1.1 介紹
agg
方法是pandas中用於數據集彙總的函數,它可以將聚合行爲應用於一組函數(字符串、函數或名稱),這些函數將被應用於每一行或列,並返回單個結果,以使彙總多個函數變得更加容易。
它主要用於列表等結構化數據彙總,例如:
• 根據某幾列計算某幾列的值
• 根據某幾列聚合數據
• 根據某幾列計算多個數據表的值
使用 pandas 中的 agg
方法可以實現多種數據彙總操作:
1、傳入一個agg
函數,只需要一個聚合函數作爲參數,默認地調用給定的聚合函數每一列:
import numpy as np
data.agg(np.mean)
2、傳入一個字典,在字典中,columns作爲鍵,對應的值則是函數,根據指定的列選擇聚合函數:
import numpy as np
data.agg({'height': np.mean, 'weight': np.sum})
3、傳入一個函數,可以傳入自定義的函數:
def myfunc(x):
retrun x.max() - x.min()
data.agg(myfunc)
pandas的agg
函數也可以在grouby
中使用,以實現按分組聚合指定的統計列的結果。例如:
import numpy as np
data.groupby('Category').agg(np.mean)
此語句將使用Category分組,並用np.mean
方法聚合該分組下的所有統計列的結果,並返回一個分組結合的聚合結果DataFrame。
1.2 使用案例
首先模擬出一組學生成績表數據:
import numpy as np
import pandas as pd
# 條件
cust_list = ['張三', '李四', '王五', '趙六']
item_list = ['蘋果', '香蕉', '橘子', '南瓜']
price_list = [10, 5, 6, 8]
quant_list = [5, 3, 4, 7]
# 創建DataFrame
df = pd.DataFrame({'客戶': np.random.choice(cust_list, size=20),
'商品': np.random.choice(item_list, size=20),
'價格': np.random.choice(price_list, size=20),
'數量': np.random.choice(quant_list, size=20),
})
# 查看數據
df
客戶 | 商品 | 價格 | 數量 | |
---|---|---|---|---|
0 | 張三 | 蘋果 | 10 | 3 |
1 | 趙六 | 蘋果 | 8 | 3 |
2 | 王五 | 南瓜 | 8 | 5 |
3 | 趙六 | 橘子 | 5 | 5 |
4 | 張三 | 橘子 | 8 | 4 |
5 | 趙六 | 橘子 | 5 | 7 |
6 | 張三 | 蘋果 | 8 | 4 |
7 | 趙六 | 橘子 | 10 | 5 |
8 | 趙六 | 蘋果 | 5 | 3 |
9 | 趙六 | 橘子 | 5 | 5 |
10 | 李四 | 香蕉 | 5 | 7 |
11 | 趙六 | 香蕉 | 10 | 3 |
12 | 李四 | 蘋果 | 5 | 7 |
13 | 張三 | 香蕉 | 6 | 4 |
14 | 王五 | 蘋果 | 5 | 5 |
15 | 趙六 | 橘子 | 10 | 3 |
16 | 李四 | 香蕉 | 10 | 7 |
17 | 李四 | 橘子 | 10 | 3 |
18 | 李四 | 橘子 | 10 | 5 |
19 | 王五 | 橘子 | 5 | 4 |
統計每個客戶購買的商品總數量:
df.groupby('客戶')[['數量']].agg(np.sum)
數量 | |
---|---|
客戶 | |
張三 | 15 |
李四 | 29 |
王五 | 14 |
趙六 | 34 |
df.groupby('客戶').agg(總數=pd.NamedAgg(column='數量', aggfunc=np.sum))
總數 | |
---|---|
客戶 | |
張三 | 15 |
李四 | 29 |
王五 | 14 |
趙六 | 34 |
統計每個客戶購買的每種商品數量:
def myfunc(x):
return np.sum(x)
df.groupby(['客戶', '商品'])[['數量']].agg(myfunc)
數量 | ||
---|---|---|
客戶 | 商品 | |
張三 | 橘子 | 4 |
蘋果 | 7 | |
香蕉 | 4 | |
李四 | 橘子 | 8 |
蘋果 | 7 | |
香蕉 | 14 | |
王五 | 南瓜 | 5 |
橘子 | 4 | |
蘋果 | 5 | |
趙六 | 橘子 | 25 |
蘋果 | 6 | |
香蕉 | 3 |
統計客戶購買的商品個數以及購買商品的最大最小總計:
df.groupby('客戶').agg({'數量': [np.max, np.min, np.sum], '商品': np.size})
數量 | 商品 | |||
---|---|---|---|---|
amax | amin | sum | size | |
客戶 | ||||
張三 | 4 | 3 | 15 | 4 |
李四 | 7 | 3 | 29 | 5 |
王五 | 5 | 4 | 14 | 3 |
趙六 | 7 | 3 | 34 | 8 |
2 transform方法
2.1 介紹
pandas的transform方法是分組變換的一個重要功能,作用是對每個組進行某種變換,以計算每個分組的統計值或利用轉換函數來改變每組中的值。
可以通過transform方法來實現一些數據相關的功能,例如:分組標準化(Z-score),歸一化(Min-Max scale),缺失值處理(均值填充或其他策略)等。
result = df.groupby('group').transform(lambda x: (x - x.mean()) / x.std())
transform
方法可以對每一個group進行一些變換,然後返回一個新的DataFrame,它包含每一個group的變換後的新值。
轉換後的數據框仍然與原來分組前的數據框位置和行數一致。
2.2 使用案例
先模擬生成一組採購訂單數據信息:
import pandas as pd
import numpy as np
import string
import random
# 隨機生成5個訂單號
order_no_list = [''.join(random.choices(string.ascii_uppercase + string.digits, k=8)) for i in range(5)]
# 生成採購數量
order_num_list = np.random.randint(1,11, size= 20)
# 構造字典
df = {
'採購訂單號': np.random.choice(order_no_list, size=20),
'採購數量': np.random.choice(order_num_list, size=20)
}
# 傳入字典構造DataFrame
df = pd.DataFrame(df)
df
採購訂單號 | 採購數量 | |
---|---|---|
0 | DLPERDUD | 5 |
1 | 4UNV1UFJ | 6 |
2 | QR2ASQTX | 6 |
3 | JZLAS8AY | 1 |
4 | 6TBOCEQT | 6 |
5 | DLPERDUD | 6 |
6 | 4UNV1UFJ | 8 |
7 | 6TBOCEQT | 1 |
8 | QR2ASQTX | 2 |
9 | JZLAS8AY | 8 |
10 | JZLAS8AY | 1 |
11 | 4UNV1UFJ | 7 |
12 | 6TBOCEQT | 6 |
13 | 6TBOCEQT | 9 |
14 | QR2ASQTX | 2 |
15 | 4UNV1UFJ | 4 |
16 | 6TBOCEQT | 3 |
17 | QR2ASQTX | 3 |
18 | QR2ASQTX | 9 |
19 | DLPERDUD | 7 |
按照採購訂單號分組統計採購數量的合計值:
df['總數'] = df.groupby('採購訂單號')['採購數量'].transform(np.sum)
df
採購訂單號 | 採購數量 | 總數 | |
---|---|---|---|
0 | DLPERDUD | 5 | 18 |
1 | 4UNV1UFJ | 6 | 25 |
2 | QR2ASQTX | 6 | 22 |
3 | JZLAS8AY | 1 | 10 |
4 | 6TBOCEQT | 6 | 25 |
5 | DLPERDUD | 6 | 18 |
6 | 4UNV1UFJ | 8 | 25 |
7 | 6TBOCEQT | 1 | 25 |
8 | QR2ASQTX | 2 | 22 |
9 | JZLAS8AY | 8 | 10 |
10 | JZLAS8AY | 1 | 10 |
11 | 4UNV1UFJ | 7 | 25 |
12 | 6TBOCEQT | 6 | 25 |
13 | 6TBOCEQT | 9 | 25 |
14 | QR2ASQTX | 2 | 22 |
15 | 4UNV1UFJ | 4 | 25 |
16 | 6TBOCEQT | 3 | 25 |
17 | QR2ASQTX | 3 | 22 |
18 | QR2ASQTX | 9 | 22 |
19 | DLPERDUD | 7 | 18 |
篩選出採購訂單號對應的採購總數大於20的數據:
# 篩選
df[df.groupby('採購訂單號')['採購數量'].transform(np.sum) > 20]
採購訂單號 | 採購數量 | 總數 | |
---|---|---|---|
1 | 4UNV1UFJ | 6 | 25 |
2 | QR2ASQTX | 6 | 22 |
4 | 6TBOCEQT | 6 | 25 |
6 | 4UNV1UFJ | 8 | 25 |
7 | 6TBOCEQT | 1 | 25 |
8 | QR2ASQTX | 2 | 22 |
11 | 4UNV1UFJ | 7 | 25 |
12 | 6TBOCEQT | 6 | 25 |
13 | 6TBOCEQT | 9 | 25 |
14 | QR2ASQTX | 2 | 22 |
15 | 4UNV1UFJ | 4 | 25 |
16 | 6TBOCEQT | 3 | 25 |
17 | QR2ASQTX | 3 | 22 |
18 | QR2ASQTX | 9 | 22 |
# 上面的篩選也可以這麼寫
df[df.groupby('採購訂單號')['採購數量'].transform(lambda x: x.sum() > 20)]
採購訂單號 | 採購數量 | 總數 | |
---|---|---|---|
1 | 4UNV1UFJ | 6 | 25 |
2 | QR2ASQTX | 6 | 22 |
4 | 6TBOCEQT | 6 | 25 |
6 | 4UNV1UFJ | 8 | 25 |
7 | 6TBOCEQT | 1 | 25 |
8 | QR2ASQTX | 2 | 22 |
11 | 4UNV1UFJ | 7 | 25 |
12 | 6TBOCEQT | 6 | 25 |
13 | 6TBOCEQT | 9 | 25 |
14 | QR2ASQTX | 2 | 22 |
15 | 4UNV1UFJ | 4 | 25 |
16 | 6TBOCEQT | 3 | 25 |
17 | QR2ASQTX | 3 | 22 |
18 | QR2ASQTX | 9 | 22 |