修改特定组的 pandas 多索引值

Modify pandas multiindex value for a particular group

假设我有一个 pandas 具有三个不同级别的 MultiIndex DataFrame:

arrays = [['2020-03-30', '2020-03-30', '2020-03-30', '2020-04-15', '2020-04-15', '2020-04-15', '2020-05-10', '2020-05-10', '2020-06-10'], ['Firm1', 'Firm1', 'Firm2', 'Firm1', 'Firm2', 'Firm2', 'Firm1', 'Firm1', 'Firm1'], ['2022-01-01', '2023-02-01', '2021-01-05', '2021-04-01', '2022-01-01', '2024-02-01', '2021-02-05', '2022-04-01', '2022-04-01']]
idx = pd.MultiIndex.from_arrays(arrays, names = ('Buy_date', 'Firm', 'Sell_date'))
df = pd.DataFrame(np.zeros(9), index = idx)
df

                               0
Buy_date   Firm  Sell_date      
2020-03-30 Firm1 2022-01-01  0.0
                 2023-02-01  0.0
           Firm2 2021-01-05  0.0
2020-04-15 Firm1 2021-04-01  0.0
           Firm2 2022-01-01  0.0
                 2024-02-01  0.0
2020-05-10 Firm1 2021-02-05  0.0
                 2022-04-01  0.0
2020-06-10 Firm1 2022-04-01  0.0

对于给定的买入日期,我想更改公司 1 的最大 Sell_date 指数值并将其设置为 01.01.2030。所以输出应该是:

Buy_date   Firm  Sell_date      
2020-03-30 Firm1 2022-01-01  0.0
                 2030-01-01  0.0
           Firm2 2021-01-05  0.0
2020-04-15 Firm1 2030-01-01  0.0
           Firm2 2022-01-01  0.0
                 2024-02-01  0.0
2020-05-10 Firm1 2021-02-05  0.0
                 2030-01-01  0.0
2020-06-10 Firm1 2030-01-01  0.0

有人知道怎么做吗?

这是使用 set_index 的一种方法,并附加一个具有所需修改的新索引级别。还使用 groupby.transform 获取最大日期:

max_dates = df.reset_index(level='Sell_date').groupby(level=[0,1])['Sell_date'].transform('max')
df = df.set_index(df.index.get_level_values(2)
                  .where((df.index.get_level_values(1)!='Firm1') | 
                         (df.index.get_level_values(2)!=max_dates), '2030-01-01'), 
                  append=True).droplevel(2)

更直接的方法是使用 reset_index,修改 DataFrame 并使用新列设置索引:

df1 = df.reset_index()
max_date = df1.groupby(['Buy_date','Firm'])['Sell_date'].transform('max')
df1.loc[df1['Sell_date'].eq(max_date) & df1['Firm'].eq('Firm1'), 'Sell_date'] = '2030-01-01'
df = df1.set_index(['Buy_date','Firm','Sell_date'])

输出:

                               0
Buy_date   Firm  Sell_date      
2020-03-30 Firm1 2022-01-01  0.0
                 2030-01-01  0.0
           Firm2 2021-01-05  0.0
2020-04-15 Firm1 2030-01-01  0.0
           Firm2 2022-01-01  0.0
                 2024-02-01  0.0
2020-05-10 Firm1 2021-02-05  0.0
                 2030-01-01  0.0
2020-06-10 Firm1 2030-01-01  0.0