这应该很简单,但我花了太多的行来完成:
我有一个pandas数据框架,索引为id每年和.
对于A组和B组,我只想回填2022到2021的值(2019的值保持不变)。
这个方法最终成功了,但是很麻烦:
df = df.swaplevel()
# create a frame with backfilled values
dfbf = df.loc[[2021,2022]].groupby('id')['value'].bfill(limit=1).to_frame()
df = df.join(dfbf, rsuffix = '_fill')
df = df.reset_index(level = "id")
df['value'].loc[2021] = df.loc[2021][['value', 'value_fill']].sum(axis = 1)
df = df.set_index(['id'], append=True).swaplevel()
的例子:
<表类>价值 价值 tbody><<tr>id 年 id 年 2019 2019 2020 1 2020 1 2021 2021 3 2022 3 2022 3 B2019 B 2019 B2020 12 B 2020 12 B2021 B 2021 11 B2022 11 B 2022 11 表类>
Select rows by first byDataFrame.loc
withGroupBy.bfill
withDataFrame.update
:
df.update(df.loc[:, [2021,2022], :].groupby('id')['value'].bfill(limit=1))
print (df)
value
id year
A 2019 NaN
2020 1.0
2021 3.0
2022 3.0
B 2019 NaN
2020 12.0
2021 11.0
2022 11.0
或者对预期的行使用掩码(为了提高性能,在两边过滤——只处理选定的行,而不是所有行):
#include
m = df.index.get_level_values('year').isin([2021,2022])
#exclude
#m = df.index.get_level_values('year') != 2019
df.loc[m, 'value'] = df[m].groupby('id')['value'].bfill(limit=1)
print (df)
value
id year
A 2019 NaN
2020 1.0
2021 3.0
2022 3.0
B 2019 NaN
2020 12.0
2021 11.0
2022 11.0
您可以简单地将要替换的值子集使用loc
和'year'级别的条件来避免2019:
df.loc[df.index.get_level_values('year')!=2019] = df.groupby(level=0).bfill()
输出:
value
id year
A 2019 NaN
2020 1.0
2021 3.0
2022 3.0
B 2019 NaN
2020 12.0
2021 11.0
2022 11.0