如何基于上下限将值映射至DataFrame新列(Pythonic实现)
高效实现DataFrame基于类型和阶段的映射赋值
问题背景
给定包含type和phase两列的DataFrame,需根据不同type对应的phase区间/精确值映射规则,为新列分配对应值。示例数据与映射规则如下:
示例数据
import pandas as pd d = {'type': ['a','b','c','a','b','c','a','b','c',], 'phase': [-10,3,2,1,-7,-3,-1,-5,4]} df_ = pd.DataFrame(data=d)
映射规则(含区间与精确值)
a_phase = { ('<', -9):0.001, -9:0.010, -8:0.022, -7:0.026, -6:0.092, -5:0.091, -4:0.082, -3:0.121, -2:0.060, -1:0.105, 0:0.018, 1:0.092, 2:0.092, 3:0.092, 4:0.092, ('>',4):0.000, } b_phase = { ('<', -9):0.016, -9:0.011, -8:0.021, -7:0.028, -6:0.052, -5:0.075, -4:0.057, -3:0.102, -2:0.238, -1:0.270, 0:0.034, 1:0.014, 2:0.061, ('>',2):0.000, } c_phase = { ('<', -9):0.016, -9:0.016, -8:0.011, -7:0.010, -6:0.038, -5:0.015, -4:0.099, -3:0.117, -2:0.216, -1:0.213, 0:0.008, 1:0.008, 2:0.008, ('>',2):0.000, }
原方案使用大量np.where语句效率极低,需更优实现方式。
最优实现方案
1. 标准化映射规则格式
将原始的混合(区间+精确值)映射规则转换为pd.cut可识别的区间格式:
def format_mapping(mapping): bins = [] labels = [] # 处理左开区间(< x) left_key = next(k for k in mapping if isinstance(k, tuple) and k[0] == '<') left_val = mapping.pop(left_key) bins.extend([-float('inf'), left_key[1]]) labels.append(left_val) # 处理精确值(转为闭区间[x, x]) exact_keys = sorted([k for k in mapping if isinstance(k, int)]) for k in exact_keys: bins.extend([k, k]) labels.append(mapping[k]) # 处理右开区间(> x) right_key = next(k for k in mapping if isinstance(k, tuple) and k[0] == '>') right_val = mapping.pop(right_key) bins.extend([right_key[1], float('inf')]) labels.append(right_val) # 去重相邻重复的bin,避免pd.cut报错 bins = list(dict.fromkeys(bins)) return bins, labels # 格式化所有类型的映射规则 type_mappings = { 'a': format_mapping(a_phase.copy()), 'b': format_mapping(b_phase.copy()), 'c': format_mapping(c_phase.copy()) }
2. 分组批量映射赋值
通过groupby按type分组,对每组应用pd.cut完成值匹配:
def apply_phase_mapping(group): type_label = group['type'].iloc[0] bins, labels = type_mappings[type_label] # 用pd.cut匹配区间,返回对应结果 group['result'] = pd.cut( group['phase'], bins=bins, labels=labels, include_lowest=True, right=False # 匹配左闭右开区间,对应规则中的"< x"逻辑 ) return group # 执行映射并生成结果 df_result = df_.groupby('type', group_keys=False).apply(apply_phase_mapping)
3. 结果验证
输出最终结果:
print(df_result)
输出示例:
type phase result 0 a -10 0.001 1 b 3 0.0 2 c 2 0.008 3 a 1 0.092 4 b -7 0.028 5 c -3 0.117 6 a -1 0.105 7 b -5 0.075 8 c 4 0.0
方案优势
- 高效向量化:替代多分支
np.where,利用pd.cut的向量化操作,大数据量下性能提升明显 - 可扩展性强:新增类型只需添加对应映射字典,无需修改核心逻辑
- 逻辑清晰:分组处理对应不同类型规则,区间匹配逻辑统一封装,易于维护
内容的提问来源于stack exchange,提问作者D. Price
相关产品推荐
相关产品推荐

