如何基于多列值定义函数生成新列?Pandas代码问题求助
问题描述
现有如下Pandas DataFrame数据:
| Activity | Hazard | Condition | consequence |
|---|---|---|---|
| welding | fire | chamber | high |
| painting | falling | none | medium |
需要基于Activity、Hazard、Condition、consequence四列生成第五列,规则如下:
- 若
Activity列包含"working"或"performing",返回none - 若
Condition列包含none,返回none - 否则返回
Hazard+ " is " +Condition+ " impact " +consequence的拼接结果
我写了带正则的Python代码,但没得到预期结果,代码如下:
Dt1 = ['working','performing duties'] Dt2 = ["none"] Dt1_regex = "|".join(Dt1) Dt2_regex = "|".join(Dt2) def clean(x): if datafile.Activity.str.contains (Dt1_regex, regex=True) | datafile.Condition.str.contains(Dt2_regex, regex=True): return 'none' else: return datafile.Hazard.map(str) + " is " + datafile.Condition.map(str)+" impact " + datafile.consequence.map(str) datafile['combined'] = datafile.apply(clean)
问题分析
你的代码有两个关键错误:
- 错误使用整列判断而非单行:在
clean函数里,你直接调用datafile.Activity.str.contains(...),这会返回整个列的布尔判断结果,而不是当前行的结果。apply传入的x是单行数据,应该用x['Activity']来访问当前行的对应列值。 - 返回值类型不匹配:
else分支返回的是一整列的拼接结果(Series类型),但apply要求每个函数调用返回单个字符串,导致赋值失败。
解决方案
方案1:修正apply函数写法
调整函数逻辑,针对单行数据处理:
import pandas as pd # 构造示例数据(已有数据可跳过此步) datafile = pd.DataFrame({ 'Activity': ['welding', 'painting'], 'Hazard': ['fire', 'falling'], 'Condition': ['chamber', 'none'], 'consequence': ['high', 'medium'] }) Dt1 = ['working','performing duties'] Dt2 = ["none"] Dt1_regex = "|".join(Dt1) Dt2_regex = "|".join(Dt2) def clean(x): # 检查当前行的Activity是否匹配正则,或Condition是否为none activity_match = pd.Series([x['Activity']]).str.contains(Dt1_regex, regex=True).iloc[0] if activity_match or x['Condition'] == Dt2_regex: return 'none' else: return f"{x['Hazard']} is {x['Condition']} impact {x['consequence']}" # 指定axis=1,按行应用函数 datafile['combined'] = datafile.apply(clean, axis=1)
方案2:向量化操作(推荐)
用Pandas原生的向量化方法替代apply,效率更高,代码更简洁:
import pandas as pd datafile = pd.DataFrame({ 'Activity': ['welding', 'painting'], 'Hazard': ['fire', 'falling'], 'Condition': ['chamber', 'none'], 'consequence': ['high', 'medium'] }) Dt1 = ['working','performing duties'] Dt2 = ["none"] Dt1_regex = "|".join(Dt1) Dt2_regex = "|".join(Dt2) # 生成布尔掩码:标记需要返回'none'的行 mask = datafile['Activity'].str.contains(Dt1_regex, regex=True) | datafile['Condition'].str.contains(Dt2_regex, regex=True) # 用where方法赋值:满足mask的行设为'none',否则拼接字符串 datafile['combined'] = ( datafile['Hazard'].astype(str) + " is " + datafile['Condition'].astype(str) + " impact " + datafile['consequence'].astype(str) ).where(~mask, 'none')
运行后得到的combined列结果如下:
| Activity | Hazard | Condition | consequence | combined |
|---|---|---|---|---|
| welding | fire | chamber | high | fire is chamber impact high |
| painting | falling | none | medium | none |
内容的提问来源于stack exchange,提问作者Sonali
相关产品推荐
相关产品推荐

