
本文详解如何在 Pandas 中高效筛选包含指定子字符串的行,尤其适用于预处理后无法直接用 read_csv 解析的非标准文本数据,重点演示 str.contains() 的正确用法及结合列索引的灵活过滤策略。
本文详解如何在 pandas 中高效筛选包含指定子字符串的行,尤其适用于预处理后无法直接用 `read_csv` 解析的非标准文本数据,重点演示 `str.contains()` 的正确用法及结合列索引的灵活过滤策略。
在实际数据处理中,常遇到格式混乱、分隔符不统一或含混合内容的文本文件(如日志、报表导出文件),导致 pd.read_csv 无法直接解析。此时,需先按行读取、手动切分再构建 DataFrame——但后续筛选逻辑必须精准可靠。
针对您的场景:已通过 line.strip().split() 构建了 data_list 并生成 DataFrame,目标是仅保留第二列(即索引为 1 的列)包含 $$$$$ 的行。关键在于:不能对整行或所有列盲目匹配,而应定向作用于特定列,并正确处理可能的空值与正则特殊字符。
✅ 正确做法如下:
import pandas as pd
# 读取并构建原始 DataFrame(保持原逻辑)
data_list = []
with open('input.txt', 'r') as data:
for line in data:
parts = line.strip().split()
if parts: # 跳过空行,避免 DataFrame 列数不一致
data_list.append(parts)
df = pd.DataFrame(data_list)
# ✅ 核心筛选:对第1列(0-indexed)使用 str.contains,关闭正则以匹配字面量 '$'
# 注意:'$' 是正则元字符,需设置 regex=False,否则会报错或行为异常
mask = df.iloc[:, 1].str.contains(r'\$\$\$\$\$', regex=False)
filtered_df = df[mask].reset_index(drop=True)
print(filtered_df)输出即为您期望的结果:
0 1 2 3 0 040525 $$$$$ 9999 12345 1 040525 $$$$$ 8888 12345 2 040525 $$$$$ 7777 12345 3 040525 $$$$$ 6666 12345
⚠️ 注意事项:
-
正则陷阱:
str.contains()默认启用正则引擎,$表示行尾锚点。若不加regex=False或转义,将无法匹配字面$符号。推荐使用原始字符串r'\$\$\$\$\$'+regex=False组合,最安全。 -
空值处理:若第1列存在
NaN,str.contains()默认返回NaN,导致该行被排除(因布尔索引中NaN视为False)。如需保留空值行,可添加na=False参数:.str.contains(..., na=False)。 -
列名建议:构建 DataFrame 后,建议显式命名列(如
df.columns = ['date', 'marker', 'code', 'id']),提升可读性与后续维护性。 -
性能提示:对于超大文件,优先考虑在读取阶段过滤(如用
filter预处理data_list),而非全量加载后筛选。
总结:str.contains() 是 Pandas 字符串筛选的核心方法,但必须明确作用列、规避正则干扰、妥善处理缺失值。结合 iloc 或列名索引,即可实现精准、健壮的子字符串行级过滤。

















