基于多条件更新DataFrame的Value列及报错解决
问题:Pandas多条件更新DataFrame列异常
原始DataFrame
import pandas as pd import numpy as np df = pd.DataFrame([('Ve_Paper', 'Buy', '-','Canada',np.NaN), ('Ve_Gasoline', 'Sell', 'Done','Britain',np.NaN), ('Ve_Water', 'Sell','-','Canada',np.NaN), ('Ve_Plant', 'Buy', 'Good','China',np.NaN), ('Ve_Soda', 'Sell', 'Process','Germany',np.NaN)], columns=['Name', 'Action','Status','Country','Value'])
更新需求
基于多条件更新Value列:
- 若
Action为Sell:- 当
Status不为'-'时,将Country的前两个字符赋值给Value - 当
Status为'-'时,将Name去掉'Ve_'后的内容赋值给Value
- 当
- 若
Action不为Sell,Value保持np.NaN
尝试的错误代码
df['Value'] = np.where(df['Action']== 'Sell',df['Country'].str[:2] if df['Status'].str != '-' else df['Name'].str[3:],df['Value'])
执行后输出异常,出现<pandas.core.strings.StringMethods object at 0x000001EDB8F662B0>这类错误结果,不符合预期。
期望输出
Name Action Status Country Value Ve_Paper Buy - Canada NaN # Action不为Sell,保持原值 Ve_Gasoline Sell Done Britain Br # Action为Sell且Status不为'-',取Country前两位 Ve_Water Sell - Canada Water # Action为Sell且Status为'-',取Name去掉'Ve_'后的内容 Ve_Plant Buy Good China NaN Ve_Soda Sell Process Germany Ge
解决方案
方法1:嵌套使用np.where
原代码问题在于用Python原生if-else处理Series级判断,无法实现逐元素逻辑。改用嵌套np.where即可逐元素判断赋值:
df['Value'] = np.where( df['Action'] == 'Sell', np.where(df['Status'] != '-', df['Country'].str[:2], df['Name'].str[3:]), df['Value'] )
方法2:使用apply自定义函数
逐行处理逻辑,可读性更强:
def update_value(row): if row['Action'] == 'Sell': return row['Country'][:2] if row['Status'] != '-' else row['Name'][3:] return row['Value'] df['Value'] = df.apply(update_value, axis=1)
方法3:分步使用loc赋值
分条件定位后直接赋值,逻辑清晰,适合复杂场景:
# 条件1:Action为Sell且Status不为'-',赋值Country前两位 df.loc[(df['Action'] == 'Sell') & (df['Status'] != '-'), 'Value'] = df['Country'].str[:2] # 条件2:Action为Sell且Status为'-',赋值Name去掉'Ve_'后的内容 df.loc[(df['Action'] == 'Sell') & (df['Status'] == '-'), 'Value'] = df['Name'].str[3:] # Action不为Sell的情况保持原Value,无需额外处理
以上三种方法均可得到符合预期的结果,可根据场景和习惯选择。
内容的提问来源于stack exchange,提问作者user18562240
相关产品推荐
相关产品推荐

