
本文介绍如何高效筛选 DataFrame 中某字符串列同时包含指定多个子字符串的所有行,核心是利用 str.contains() 生成布尔矩阵,并通过 np.all(..., axis=0) 按行聚合逻辑条件。
本文介绍如何高效筛选 dataframe 中某字符串列同时包含指定多个子字符串的所有行,核心是利用 `str.contains()` 生成布尔矩阵,并通过 `np.all(..., axis=0)` 按行聚合逻辑条件。
在 Pandas 中,对字符串列进行多关键词“与”(AND)条件过滤时,不能直接对 Series 使用 Python 内置的 all() 函数——因为 word in df['question'] 会报错(Series 不支持直接用 in 判断),而 all([...]) 作用于布尔列表时又会提前折叠为单个标量值(如 True/False),导致 df[False] 被误解析为列索引查找,从而引发 KeyError: False。
正确做法是:对每个子字符串分别调用 Series.str.contains(),得到一组长度相同的布尔 Series(即一个布尔矩阵),再沿行方向(axis=0)执行逻辑“全为真”判断。推荐使用 numpy.all() 或更简洁的 Pandas 链式写法(如 pd.concat(..., axis=1).all(axis=1))。
以下为完整示例代码:
import numpy as np
import pandas as pd
# 构造示例数据
df = pd.DataFrame({
"question": [
"Who is the King of England?",
"Where is England?",
"England King",
"King",
"The Queen rules England"
]
})
# 待匹配的子字符串列表
keywords = ["King", "England"]
# 方法一:使用 np.all + 列表推导式(推荐,简洁高效)
mask = np.all([df['question'].str.contains(kw, na=False) for kw in keywords], axis=0)
filtered_df = df[mask].copy()
print(filtered_df)
输出结果:
question 0 Who is the King of England? 2 England King
⚠️ 注意事项:
- str.contains() 默认区分大小写;如需忽略大小写,添加参数 case=False(例如 .str.contains(kw, case=False, na=False));
- na=False 参数至关重要:它将缺失值(NaN)统一视为 False,避免 NaN 导致布尔运算失败或意外结果;
- 若关键词含正则特殊字符(如 .、*、?),应设置 regex=False 避免误匹配,或对关键词预转义;
- 性能提示:对于大规模数据,可考虑先用 str.lower() 统一转换再匹配,比重复设置 case=False 更高效。
总结:多关键词“必须全部存在”的字符串过滤,本质是行级布尔逻辑交集运算。牢记勿用 Python 原生 all() 直接包裹 Series 表达式,而应借助向量化方法构建逐行判断掩码——这是 Pandas 字符串过滤的典型范式。











