pandas使用apply时按列名范围索引求和触发IndexingError如何解决
问题原因
你的推测完全正确。df.apply(func, axis=1)逐行运算时,传入自定义函数的参数x是一维Series,索引就是原DataFrame的列名,仅存在一个维度,你用x.loc[:,'a':'b']这种二维索引写法,传入了行、列两个索引参数,自然会触发Too many indexers报错。
修正写法(直接满足需求)
如果要保留apply写法实现按列名范围求和,直接对单行Series做切片求和即可,不需要加.loc也不需要指定axis参数:
# 修正后的b月末库存计算函数 def b_stock(x): total = x['A1'] + x['a':'b'].sum() return 0 if x['A2'] > total else total df['stock_on_b'] = df.apply(b_stock, axis=1)
如果需要同时计算b、c、d三个月的库存,不用重复写三个函数,可以封装成通用函数,传入截止月份即可:
def cal_month_end_stock(x, end_month): total_available = x['A1'] + x['a':end_month].sum() return max(0, total_available - x['A2']) # 批量生成三个月份的库存列 for month in ['b', 'c', 'd']: df[f'stock_on_{month}'] = df.apply(cal_month_end_stock, axis=1, end_month=month)
更高效的优化方案(避免逐行apply,适合大数据量场景)
用pandas向量化的累计求和函数cumsum实现,运算效率远高于逐行apply:
# 先计算a到d列逐列的累计和 month_cum = df.loc[:, 'a':'d'].cumsum(axis=1) # 用clip方法直接把小于0的结果置为0 df['stock_on_b'] = (df['A1'] + month_cum['b'] - df['A2']).clip(lower=0) df['stock_on_c'] = (df['A1'] + month_cum['c'] - df['A2']).clip(lower=0) df['stock_on_d'] = (df['A1'] + month_cum['d'] - df['A2']).clip(lower=0)
注意:你示例中给出的冗余写法重复加了两次
x['A1'],属于书写错误,上述代码已经修正了该逻辑,和你给出的库存计算公式完全匹配。
内容的提问来源于stack exchange,提问作者Jonas Palačionis
相关产品推荐
相关产品推荐

