如何通过Pandas read_csv筛选首字段符合条件的有效CSV行?
解决方案
核心问题分析
你之前用skiprows=(lambda x: x not in counties)无效的原因是:skiprows的lambda函数接收的参数是行号(整数),而非行内容。行号是0、1、2...这类数字,和郡名列表比对永远不匹配,导致逻辑完全错误。
方案一:先过滤有效行再读取(适用于行格式问题不影响首字段识别)
先通过Python内置文件操作读取所有行,只保留首字段属于目标郡名的行,再将过滤后的内容传给pd.read_csv:
import pandas as pd from io import StringIO # 目标郡名列表 counties = ["Bedfordshire", "Berkshire", "Bristol", ... , "Worcestershire"] county_set = set(counties) # 转为集合提升查询效率 filtered_content = [] with open('data/libraries.csv', 'r', encoding='utf-8') as f: # 保留表头行 header = f.readline() filtered_content.append(header) # 遍历每一行过滤 for line in f: # 提取首字段(处理可能的引号包裹) first_col = line.split(',')[0].strip().strip('"') if first_col in county_set: filtered_content.append(line) # 将过滤后的内容转为DataFrame df = pd.read_csv(StringIO(''.join(filtered_content)))
方案二:处理行拆分问题后再过滤(适用于存在行内容被拆分的情况)
如果CSV存在行内容被拆分到多行的情况,先合并不完整的行,再过滤首字段符合要求的行:
import pandas as pd from io import StringIO counties = ["Bedfordshire", "Berkshire", "Bristol", ... , "Worcestershire"] county_set = set(counties) filtered_content = [] with open('data/libraries.csv', 'r', encoding='utf-8') as f: header = f.readline() filtered_content.append(header) current_incomplete_line = "" for line in f: stripped_line = line.strip() if not stripped_line: continue # 尝试提取当前行的首字段 first_col = stripped_line.split(',')[0].strip().strip('"') if first_col in county_set: # 如果当前行是有效行,先清空之前的不完整行(无效) current_incomplete_line = "" filtered_content.append(line) else: # 首字段无效,合并到上一行(视为行拆分) current_incomplete_line += stripped_line # 处理最后一行可能的不完整内容 if current_incomplete_line: final_first_col = current_incomplete_line.split(',')[0].strip().strip('"') if final_first_col in county_set: filtered_content.append(current_incomplete_line + '\n') df = pd.read_csv(StringIO(''.join(filtered_content)))
关键优化点
- 把郡名列表转为集合:列表的
in操作是O(n)时间复杂度,集合是O(1),在数据量较大时能显著提升过滤效率。 - 处理引号包裹:如果首字段被双引号包裹(比如
"Bedfordshire",...),用strip('"')去除引号后再比对。
内容的提问来源于stack exchange,提问作者Rykari
相关产品推荐
相关产品推荐

