Агрегация по разделам - 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)
Другие вопросы по тегам