
本文详解 pandas 中根据某列字符串是否包含特定子串,高效、准确地创建条件新列的方法,并重点纠正初学者常见的逻辑运算符误用问题。
本文详解 pandas 中根据某列字符串是否包含特定子串,高效、准确地创建条件新列的方法,并重点纠正初学者常见的逻辑运算符误用问题。
在使用 Pandas 进行数据处理时,常需基于现有字符串列的内容动态生成新列。一个典型场景是:若某列(如 df['col'])的单元格中包含字符 "a"、"b" 或 "c" 中的任意一个,则新列赋值为 "string";若含 "d"、"e" 或 "f",则赋 "other string";否则为 "default string"。
但以下写法是错误且危险的:
def function(x):
if "a" or "b" or "c" in x: # ❌ 逻辑错误!
return "string"
elif "d" or "e" or "f" in x: # ❌ 同样错误!
return "other string"
else:
return "default string"
该代码看似简洁,实则因 Python 运算符优先级与布尔求值机制导致严重逻辑偏差:
"a" or "b" or "c" in x 实际等价于 ("a") or ("b") or ("c" in x)。而非空字符串 "a" 和 "b" 在布尔上下文中恒为 True,因此整个条件恒为 True —— 所有行都会进入第一个分支,最终新列全为 "string"。
✅ 正确写法必须对每个子串单独执行 in 判断,并用 or 连接:
def assign_by_substring(x):
if "a" in x or "b" in x or "c" in x:
return "string"
elif "d" in x or "e" in x or "f" in x:
return "other string"
else:
return "default string"
df["new col"] = df["col"].apply(assign_by_substring)
更推荐使用 向量化方法 提升性能与可读性(尤其对大数据集):
# 使用 str.contains() + numpy.select()(推荐)
import numpy as np
mask1 = df["col"].str.contains(r"[abc]", na=False) # 包含 a/b/c 任一字符(正则)
mask2 = df["col"].str.contains(r"[def]", na=False) # 包含 d/e/f 任一字符
df["new col"] = np.select(
[mask1, mask2],
["string", "other string"],
default="default string"
)
⚠️ 注意事项:
- str.contains() 默认区分大小写,如需忽略大小写,添加 case=False 参数;
- 若原始列含缺失值(NaN),str.contains() 会返回 NaN,建议配合 na=False 统一设为 False;
- 正则表达式 r"[abc]" 比多次 or 更简洁高效,也支持更复杂模式(如 "apple|banana");
- 避免在 apply() 中使用耗时循环或重复字符串操作——优先选用 str 访问器和向量化函数。
总结:条件列构建的核心在于明确子串检测的语法结构,杜绝将 "a" or "b" in x 当作“a 或 b 是否在 x 中”的简写。掌握 str.contains() 与 np.select() 的组合,既能写出健壮代码,又能兼顾执行效率与维护性。











