如何按条件优先级创建Pandas DataFrame新列d?
解决Pandas条件赋值的覆盖问题
问题场景
给定如下DataFrame:
import pandas as pd df = pd.DataFrame( { 'a': [10, 20, 55], 'b': [3, 40, 33], 'c': [4, 50, 10] } )
需要创建列d,规则为:
- 优先判断
df.a > df.b,满足则d=1,不再判断后续条件 - 未满足第一个条件时,可按其他规则处理(如示例中
df.a > df.c时设为2) - 所有条件都不满足时,
d=0
目标输出:
a b c d 0 10 3 4 1.0 1 20 40 50 0.0 2 55 33 10 1.0
原代码的问题
原代码直接按顺序赋值,会出现值被覆盖的情况:
df.loc[df.a > df.b, 'd'] = 1 df.loc[df.a > df.c, 'd'] = 2 df['d'] = df.d.fillna(0)
原因是:同时满足df.a > df.b和df.a > df.c的行(比如第0行),会被第二个loc语句重新赋值为2,违背了“满足第一个条件就不再判断后续”的优先级要求。
解决方案
方法1:使用numpy.select(推荐)
numpy.select支持按条件优先级批量赋值,只需按顺序定义条件和对应值,最后设置默认值即可:
import numpy as np # 按优先级定义条件列表 conditions = [ df['a'] > df['b'], df['a'] > df['c'] # 仅当第一个条件不满足时才会判断 ] # 对应条件的取值 values = [1, 2] # 赋值,默认值设为0 df['d'] = np.select(conditions, values, default=0)
执行后得到的结果完全符合需求:
a b c d 0 10 3 4 1 1 20 40 50 0 2 55 33 10 1
方法2:分步赋值并限制范围
先将d初始化为0,再按优先级从高到低赋值,每次仅对未被赋值的行操作:
# 先设置默认值0 df['d'] = 0 # 处理最高优先级条件 df.loc[df['a'] > df['b'], 'd'] = 1 # 处理第二个条件时,仅针对d仍为0的行(即第一个条件不满足的行) df.loc[(df['d'] == 0) & (df['a'] > df['c']), 'd'] = 2
这种方法通过添加df['d'] == 0的限制,避免了对已赋值行的覆盖。
内容的提问来源于stack exchange,提问作者AmirX
相关产品推荐
相关产品推荐

