Используйте DataFrame.merge
, если не уверены, что 2020
первый для групп:
df1 = df[df['year'].eq(2020)]
df['value'] -= df.merge(df1,how='left',on=['id','variable'],suffixes=('_',''))['value'].values
print (df)
id variable year value
0 1 a 2020 0
1 1 a 2021 1
2 1 a 2022 3
3 1 b 2020 0
4 1 b 2021 5
5 1 b 2022 7
Если 2020
всегда первый для групп, используйте GroupBy.transform
с GroupBy.first
:
df['value'] -= df.groupby(['id','variable'])['value'].transform('first')
print (df)
id variable year value
0 1 a 2020 0
1 1 a 2021 1
2 1 a 2022 3
3 1 b 2020 0
4 1 b 2021 5
5 1 b 2022 7
РЕДАКТИРОВАТЬ:
Если в данных дублируются 2020
строк на группы решение сначала удалить дубликаты и только вычесть сначала значение:
print (df)
id variable year value
0 1 a 2020 3
1 1 a 2020 2
2 1 a 2022 5
3 1 b 2020 3
4 1 b 2021 8
5 1 b 2022 10
df1 = df[df['year'].eq(2020)]
df['value'] -= df.merge(df1.drop_duplicates(['id','variable']),
how='left',
on=['id','variable'],
suffixes=('_',''))['value'].values
print (df)
id variable year value
0 1 a 2020 0
1 1 a 2020 -1
2 1 a 2022 2
3 1 b 2020 0
4 1 b 2021 5
5 1 b 2022 7
или агрегированные значения, например, sum
для дедуплицированных данных:
print (df)
id variable year value
0 1 a 2020 3
1 1 a 2020 1
2 1 a 2022 5
3 1 b 2020 3
4 1 b 2021 8
5 1 b 2022 10
df = df.groupby(['id','variable','year'], as_index=False).sum()
print (df)
id variable year value
0 1 a 2020 4
1 1 a 2022 5
2 1 b 2020 3
3 1 b 2021 8
4 1 b 2022 10
df1 = df[df['year'].eq(2020)]
df['value'] -= df.merge(df1, how='left',
on=['id','variable'],
suffixes=('_',''))['value'].values
print (df)
id variable year value
0 1 a 2020 0
1 1 a 2022 1
2 1 b 2020 0
3 1 b 2021 5
4 1 b 2022 7