
本文详解如何在 Pandas 中高效筛选包含指定子字符串的行,尤其适用于无法直接使用 read_csv 解析的非结构化文本数据,重点演示列级子串匹配、链式过滤及预处理注意事项。
本文详解如何在 pandes 中高效筛选包含指定子字符串的行,尤其适用于无法直接使用 `read_csv` 解析的非结构化文本数据,重点演示列级子串匹配、链式过滤及预处理注意事项。
在实际数据处理中,常遇到格式混乱、分隔不统一的文本文件(如日志、报表或遗留系统输出),导致 pd.read_csv 无法直接解析。此时需先按行读取、手动切分,再构建 DataFrame,最后进行条件筛选——这正是本例的核心场景。
给定原始文本 input.txt,其结构松散,含标题、页脚与干扰行。我们需仅保留第二列(索引为 1)包含 $$$$$ 的有效记录。关键在于:DataFrame 构建后,对特定列执行子字符串判断,并利用布尔索引完成筛选。
以下是完整、健壮的实现流程:
import pandas as pd
data_list = []
with open('input.txt', 'r') as f:
for line in f:
parts = line.strip().split()
if parts: # 跳过空行,避免生成 NaN 或长度不一致的行
data_list.append(parts)
# 构建 DataFrame;列数可能不等,但本例中有效行均为 4 列
df = pd.DataFrame(data_list)
# 筛选:仅当第 1 列(即 df[1])存在子字符串 '$$$' 时保留该行
# 注意:使用 str.contains() 并设置 na=False 避免空值引发错误
mask = df[1].str.contains(r'\$\$\$', regex=True, na=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()默认启用正则,而$是正则元字符,因此必须转义为r'\$\$\$'或设置regex=False;推荐显式使用原始字符串加转义,语义更清晰。 - 务必添加
na=False参数,否则含NaN的行会返回NaN,导致布尔索引失败(Pandas 报TypeError: Cannot mask with non-boolean array)。 - 若原始数据列数不一致(如某些行被
split()后长度不同),DataFrame会自动用NaN填充缺失位置,此时df[1]可能含NaN——na=False同样可安全处理此情况。 - 如需进一步清洗(如去除前导零、转换数值类型),可在筛选后链式调用:
filtered_df[0] = filtered_df[0].str.lstrip('0')。
该方法兼顾灵活性与鲁棒性,是处理半结构化文本数据的标准范式之一。










