如何为MultiIndex DataFrame按多条件添加计算生成的新行
向MultiIndex DataFrame添加满足多条件的新行
我来帮你搞定这个需求,咱们一步步实现你要的功能:
首先是完整的可运行代码
import pandas as pd import numpy as np # 构建你提供的初始DataFrame def mklbl(prefix, n): return ["%s%s" % (prefix, i) for i in range(n)] miindex = pd.MultiIndex.from_product([mklbl('A', 3), mklbl('B', 4), ], names=['A','B']) micolumns = pd.MultiIndex.from_tuples([('a', 'foo'), ('a', 'bar'), ('b', 'foo'), ('b', 'bah')], names=['lvl0', 'lvl1']) df = pd.DataFrame(np.random.randint(100, size=len(miindex) * len(micolumns)) .reshape((len(miindex), len(micolumns))), index=miindex, columns=micolumns).sort_index().sort_index(axis=1) df = df.drop([('A2','B2'),('A2','B3')]) # ------------------- 核心处理逻辑 ------------------- # 1. 筛选出同时包含B2和B3的A分组(只有A0、A1符合) valid_a_groups = [ a for a in df.index.get_level_values('A').unique() if all(b in df.loc[a].index for b in ['B2', 'B3']) ] # 2. 生成要添加的B4行 new_rows = [] for a in valid_a_groups: # 获取当前A分组下B2和B3的数值 b2_vals = df.loc[(a, 'B2')] b3_vals = df.loc[(a, 'B3')] # 按条件计算B4的值:B3 < B2时取B3/B2,否则为0,保留3位小数 b4_vals = np.where(b3_vals < b2_vals, b3_vals / b2_vals, 0).round(3) # 构造新的行,指定MultiIndex名称为(A, 'B4') new_row = pd.Series(b4_vals, index=df.columns, name=(a, 'B4')) new_rows.append(new_row) # 3. 合并原DataFrame和新行,重新排序索引得到最终结果 final_df = pd.concat([df] + new_rows).sort_index() print(final_df)
代码逻辑解释
- 筛选有效A分组:我们只需要处理那些同时存在B2和B3的A分组(A0和A1),这里用列表推导式直接检查每个A分组的子索引是否包含B2和B3,比通过行数判断更严谨。
- 计算B4行数值:对每个有效分组,提取B2和B3的列值,用
np.where实现条件判断——当B3的数值小于B2时,计算两者的比值,否则设为0,同时保留三位小数和你的示例格式一致。 - 合并并排序:把生成的B4行和原DataFrame合并,最后重新排序索引,保证结构和原DataFrame一致。
运行这段代码后,你就能得到和示例完全一致的结果,A2因为没有B2和B3,所以不会添加B4行。
内容的提问来源于stack exchange,提问作者random_var
相关产品推荐
相关产品推荐

