基于多条件为Pandas DataFrame新增客户状态计算列的实现方案
实现方案
np.select是当前场景下最高效的实现方式,它基于向量化运算,比逐行遍历性能高两个数量级以上,只需要按优先级定义判断条件即可,避免逻辑覆盖。
前提约定
假设你的DataFrame包含列:customer_id、2017 Revenue、2018 Revenue、2019 Revenue、2020 Revenue、2021 Revenue,可根据实际列名替换。
完整代码示例
import pandas as pd import numpy as np # 提取各年度营收列,简化后续逻辑书写 rev_2021 = df['2021 Revenue'] rev_2020 = df['2020 Revenue'] rev_2019 = df['2019 Revenue'] rev_2018 = df['2018 Revenue'] rev_2017 = df['2017 Revenue'] # 按优先级从高到低定义判断条件,避免逻辑覆盖 conditions = [ # New:2021营收为正,2017-2020年营收均≤0 (rev_2021 > 0) & (rev_2020 <= 0) & (rev_2019 <= 0) & (rev_2018 <= 0) & (rev_2017 <= 0), # Existing:2021、2020年连续两年营收为正 (rev_2021 > 0) & (rev_2020 > 0), # Renewed:2021营收为正,2020营收≤0,2017-2019年任意一年营收为正 (rev_2021 > 0) & (rev_2020 <= 0) & ((rev_2019 > 0) | (rev_2018 > 0) | (rev_2017 > 0)), # Lost:2021营收≤0,2020营收为正 (rev_2021 <= 0) & (rev_2020 > 0), # N/A:2021营收<0,2017-2020年营收均为0 (rev_2021 < 0) & (rev_2020 == 0) & (rev_2019 == 0) & (rev_2018 == 0) & (rev_2017 == 0) ] # 定义条件对应的状态值,顺序和conditions一一对应 status_list = ['New', 'Existing', 'Renewed', 'Lost', 'N/A'] # 生成计算列,无匹配项默认填充N/A df['customer status'] = np.select(conditions, status_list, default='N/A')
易维护优化写法
如果后续需要调整统计年份范围,可以用列切片批量判断,避免逐个写列名:
# 提取2017-2020所有营收列 pre_2021_rev = df.loc[:, '2017 Revenue':'2020 Revenue'] # 判断2017-2020是否全部≤0 all_pre_2021_non_pos = (pre_2021_rev <= 0).all(axis=1) # 判断2017-2019是否有任意一年>0 any_pre_2019_pos = (pre_2021_rev.loc[:, '2017 Revenue':'2019 Revenue'] > 0).any(axis=1) # 判断2017-2020是否全部为0 all_pre_2021_zero = (pre_2021_rev == 0).all(axis=1) # 简化后的条件列表 conditions = [ (rev_2021 > 0) & all_pre_2021_non_pos, (rev_2021 > 0) & (rev_2020 > 0), (rev_2021 > 0) & (rev_2020 <=0) & any_pre_2019_pos, (rev_2021 <=0) & (rev_2020 >0), (rev_2021 <0) & all_pre_2021_zero ]
内容的提问来源于stack exchange,提问作者nb1214
相关产品推荐
相关产品推荐

