Я хочу создать новый фрейм данных из моего исходного фрейма данных, который объединяется по двум столбцам и имеет вычисляемый столбец, зависящий от суммы выбранных строк из двух других столбцов.
Вот пример df:
df = pd.DataFrame([['A','X',2000,5,3],['A','X',2001,6,2],['B','X',2000,6,3],['B','X',2001,7,2],['C','Y',2000,10,4],['C','Y',2001,12,4],['D','Y',2000,11,2],['D','Y',2001,15,1]],
columns=['ctry','rgn','year','val1, val2']))
и как это выглядит:
ctry rgn year val1 val2
0 A X 2000 5 3
1 A X 2001 6 2
2 B X 2000 6 3
3 B X 2001 7 2
4 C Y 2000 10 4
5 C Y 2001 12 4
6 D Y 2000 11 2
7 D Y 2001 15 1
В конечном итоге мне нужен новый фрейм данных, который избавится от столбца ctry
и группируется по rgn
и year
и имеет вычисляемый столбец value
, зависящий от val1
и val2
, такой, что сумма произведения val1
и val2
делится на сумму val2
для rgn
и year
:
df['value']
= ∑(val1
*val2
)/∑val2
для каждого года и года
rgn year value
0 X 2000 5.5
1 X 2001 6.5
2 Y 2000 10.333333
3 Y 2001 12.6
В итоге я успешно сделал это:
df['calc'] = df['val1'] * df['val2']
new_df = df.groupby(['rgn', 'year']).sum()
new_df['value'] = new_df['calc']/new_df['val2']
new_df = new_df.reset_index().rename_axis(None, axis=1)
new_df = new_df.drop(columns=['ctry', 'val1', 'val2', 'calc'])
Однако я хотел бы знать, есть ли более краткий способ, не требующий всех этих шагов, возможно, с использованием лямбда-функции. Ценю любую помощь, которую я получаю. Спасибо!
Предварительно вычислите value = val1*val2
, выполните groupby.sum, затем вычислите value/val1
:
out = (df.eval('value = val1*val2')
.groupby(['rgn', 'year'], as_index=False)
[['value', 'val2']].sum()
.assign(value=lambda x: x['value']/x.pop('val2'))
)
Менее эффективно, но более гибко вы также можете использовать groupby.apply:
out = (df.groupby(['rgn', 'year'])
.apply(lambda x: (x['val1']*x['val2']).sum()/x['val2'].sum(),
include_groups=False)
.reset_index(name='value')
)
Выход:
rgn year value
0 X 2000 5.500000
1 X 2001 6.500000
2 Y 2000 10.333333
3 Y 2001 12.600000