如何在双重MultiIndex的pd.DataFrame中高效实现A行与B行等值赋值?
高效修改MultiIndex DataFrame指定行值的方法
首先创建行列均为MultiIndex的DataFrame:
import pandas as pd import numpy as np columns = pd.MultiIndex.from_tuples([('a', 2), ('a', 3), ('b', 1), ('b', 3)], names=['col_1', 'col_2']) index = pd.MultiIndex.from_tuples([(pd.Timestamp('2023-03-01'), 'A'), (pd.Timestamp('2023-03-01'), 'B'), (pd.Timestamp('2023-03-01'), 'C'), (pd.Timestamp('2023-03-02'), 'A'), (pd.Timestamp('2023-03-02'), 'B'), (pd.Timestamp('2023-03-03'), 'B'), (pd.Timestamp('2023-03-03'), 'C')], names=['idx_1', 'idx_2']) data = np.arange(len(index) * len(columns)).reshape(len(index), len(columns)) df = pd.DataFrame(index=index, columns=columns, data=data)
生成的DataFrame如下:
col_1 a b col_2 2 3 1 3 idx_1 idx_2 2023-03-01 A 0 1 2 3 B 4 5 6 7 C 8 9 10 11 2023-03-02 A 12 13 14 15 B 16 17 18 19 2023-03-03 B 20 21 22 23 C 24 25 26 27
需求说明
将每个日期(idx_1)分组下的idx_2='A'行,替换为同组内idx_2='B'行的数值,预期结果如下:
col_1 a b col_2 2 3 1 3 idx_1 idx_2 2023-03-01 A 4 5 6 7 B 4 5 6 7 C 8 9 10 11 2023-03-02 A 16 17 18 19 B 16 17 18 19 2023-03-03 B 20 21 22 23 C 24 25 26 27
当前实现方式
通过unstack/stack转换结构后赋值,存在数据复制开销:
df = df.unstack() df.loc[:, pd.IndexSlice[:, :, 'A']] = df.loc[:, pd.IndexSlice[:, :, 'B']].values df = df.stack().reindex(index)
更高效的实现方法
直接通过索引定位目标行与源行,避免数据结构转换和不必要的复制:
方法1:索引匹配直接赋值
# 获取所有A行对应的日期 a_dates = df.index[df.index.get_level_values('idx_2') == 'A'].get_level_values('idx_1') # 构造对应日期的B行索引 b_indices = list(zip(a_dates, ['B']*len(a_dates))) # 直接将B行的值赋值给同日期的A行 df.loc[(a_dates, 'A'), :] = df.loc[b_indices, :].values
方法2:groupby+transform批量处理
# 按日期分组,提取每组B行的值并广播,再筛选A行完成赋值 df.loc[(slice(None), 'A'), :] = df.groupby('idx_1').transform( lambda group: group.loc[group.index.get_level_values('idx_2') == 'B'].values[0] )[df.index.get_level_values('idx_2') == 'A']
两种方法均无需对整个DataFrame进行结构转换,直接操作目标数据,大幅减少内存开销和计算时间,尤其适合大尺寸数据集。
内容的提问来源于stack exchange,提问作者JoergVanAken
相关产品推荐
相关产品推荐

