You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas中多分支IF处理多列生成新列报错求助

问题描述

我有一个名为mrp的DataFrame,想要根据rem_dys列的值,通过多分支IF逻辑计算对应p系列列的累加和,生成daily_consumption新列。逻辑规则为:rem_dys列值<=30时累加p01+p02,<=60时累加p01到p03,以此类推,步长30天。编写的代码如下:

def planning_period(x):
    if x <= 30:
        return mrp['p01'] + mrp['p02']
    elif x <= 60:
        return mrp['p01'] + mrp['p02'] + mrp['p03']
    elif x <= 90:
        return mrp['p01'] + mrp['p02'] + mrp['p03'] + mrp['p04']
    elif x <= 120:
        return mrp['p01'] + mrp['p02'] + mrp['p03'] + mrp['p04'] + mrp['p05']
    elif x <= 150:
        return mrp['p01'] + mrp['p02'] + mrp['p03'] + mrp['p04'] + mrp['p05'] + mrp['p06']
    elif x <= 180:
        return mrp['p01'] + mrp['p02'] + mrp['p03'] + mrp['p04'] + mrp['p05'] + mrp['p06'] + mrp['p07']
    elif x <= 210:
        return mrp['p01'] + mrp['p02'] + mrp['p03'] + mrp['p04'] + mrp['p05'] + mrp['p06'] + mrp['p07'] + mrp['p08']
    elif x <= 240:
        return mrp['p01'] + mrp['p02'] + mrp['p03'] + mrp['p04'] + mrp['p05'] + mrp['p06'] + mrp['p07'] + mrp['p08'] + mrp['p09']
    elif x <= 270:
        return mrp['p01'] + mrp['p02'] + mrp['p03'] + mrp['p04'] + mrp['p05'] + mrp['p06'] + mrp['p07'] + mrp['p08'] + mrp['p09'] + mrp['p10']
    else:
        return mrp['p01'] + mrp['p02'] + mrp['p03'] + mrp['p04'] + mrp['p05'] + mrp['p06'] + mrp['p07'] + mrp['p08'] + mrp['p09'] + mrp['p10'] + mrp['p11']

mrp['daily_consumption'] = mrp['rem_dys'].apply(planning_period)

运行代码时出现报错,报错信息显示期望1D数组,却得到形状为(1688,1688)的数组,同时伴随KeyError。

问题原因
  • 维度不匹配:apply调用planning_period时,每次传入的是rem_dys的单个值,但函数返回的是整个DataFrame的列相加结果(一个Series),而非当前行对应的单个累加值。当apply尝试将每个返回的Series赋值给新列的单个元素时,就会触发维度错误。
  • KeyError:大概率是DataFrame中不存在部分p系列列,或者列名拼写错误。
解决方案

方法1:修正函数,处理单行数据

修改函数使其接收整行数据,针对当前行计算对应p列的累加和:

def planning_period(row):
    x = row['rem_dys']
    cols = []
    if x <= 30:
        cols = ['p01', 'p02']
    elif x <= 60:
        cols = ['p01', 'p02', 'p03']
    elif x <= 90:
        cols = ['p01', 'p02', 'p03', 'p04']
    elif x <= 120:
        cols = ['p01', 'p02', 'p03', 'p04', 'p05']
    elif x <= 150:
        cols = ['p01', 'p02', 'p03', 'p04', 'p05', 'p06']
    elif x <= 180:
        cols = ['p01', 'p02', 'p03', 'p04', 'p05', 'p06', 'p07']
    elif x <= 210:
        cols = ['p01', 'p02', 'p03', 'p04', 'p05', 'p06', 'p07', 'p08']
    elif x <= 240:
        cols = ['p01', 'p02', 'p03', 'p04', 'p05', 'p06', 'p07', 'p08', 'p09']
    elif x <= 270:
        cols = ['p01', 'p02', 'p03', 'p04', 'p05', 'p06', 'p07', 'p08', 'p09', 'p10']
    else:
        cols = ['p01', 'p02', 'p03', 'p04', 'p05', 'p06', 'p07', 'p08', 'p09', 'p10', 'p11']
    return row[cols].sum()

mrp['daily_consumption'] = mrp.apply(planning_period, axis=1)
  • 关键改动:apply时指定axis=1,让函数接收每一行数据;函数内根据当前行的rem_dys值选择对应列,再计算该行这些列的和,返回单个数值,避免维度不匹配。

方法2:向量化处理(更高效)

针对大数据集,向量化操作比逐行apply性能更优:

# 获取所有p系列列并按顺序排序
p_cols = sorted([col for col in mrp.columns if col.startswith('p')])
# 计算每行的累加和矩阵(从p01到p11逐步累加)
cumulative_sums = mrp[p_cols].cumsum(axis=1)

# 定义rem_dys区间与对应累加列索引的映射
def get_cumulative_index(x):
    if x <= 30:
        return 1  # 对应前2列(p01-p02)的累加和,索引从0开始
    elif x <= 60:
        return 2
    elif x <= 90:
        return 3
    elif x <= 120:
        return 4
    elif x <= 150:
        return 5
    elif x <= 180:
        return 6
    elif x <= 210:
        return 7
    elif x <= 240:
        return 8
    elif x <= 270:
        return 9
    else:
        return 10  # 对应前11列(p01-p11)的累加和

# 生成每行对应的累加列索引
indices = mrp['rem_dys'].apply(get_cumulative_index)
# 根据索引提取对应累加和
mrp['daily_consumption'] = cumulative_sums.lookup(cumulative_sums.index, cumulative_sums.columns[indices])
  • 优势:避免逐行循环,处理大数据集时速度更快;逻辑更简洁,减少重复代码。

内容的提问来源于stack exchange,提问作者Mihai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 19:18:38