Агрегация по разделам - pandas Dataframe
Я ищу лучший способ агрегирования значений на основе конкретного раздела, эквивалент
SUM(TotalCost) OVER(PARTITION BY ShopName) Earnings ( SQL server)
Я могу сделать это с помощью следующих шагов в Pandas, но ищу нативный подход, который, я уверен, должен существовать
TempDF= DF.groupby(by=['ShopName'])['TotalCost'].sum()
TempDF= TempDF.reset_index()
NewDF=pd.merge(DF , TempDF, how='inner', on='ShopName')
Большое спасибо за чтение!
2 ответа
Вы можете использовать метод pandas transform() для групповых агрегаций, таких как "OVER(partition by ...)" в SQL:
import pandas as pd
import numpy as np
#create dataframe with sample data
df = pd.DataFrame({'group':['A','A','A','B','B','B'],'value':[1,2,3,4,5,6]})
#calculate AVG(value) OVER (PARTITION BY group)
df['mean_value'] = df.groupby('group').value.transform(np.mean)
df:
group value mean_value
A 1 2
A 2 2
A 3 2
B 4 5
B 5 5
B 6 5
Другой очень быстрый вариант — отобразить агрегацию обратно в исходный кадр.
df = pd.DataFrame({'group':['A','A','A','B','B','B'],'value':[1,2,3,4,5,6]})
means = df.groupby('group')['value'].mean()
df['mean_value'] = df['group'].map(means)
В некоторых случаях это самый быстрый вариант. Особенно если групп много и функция передана вgroupby
не оптимизирован. Примером может служить поиск режима каждой группы;groupby.transform
работает в два раза медленнее.
df = pd.DataFrame({'group': pd.Index(range(1000)).repeat(1000),
'value': np.random.default_rng().choice(10, size=1000000)})
%timeit df['group'].map(df.groupby('group')['value'].agg(pd.Series.mode))
# 278 ms ± 6.01 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit df.groupby('group')['value'].transform(pd.Series.mode)
# 621 ms ± 7.91 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)