在Pandas中基于值而非索引筛选行:读取Valid列为Yes的CSV数据
嘿,这个需求很实用啊——尤其是处理大CSV文件的时候,提前过滤掉不需要的行,能省不少内存和读取时间。下面给你几种最优的实现方式,按推荐程度排序:
最优方案:用Python内置csv模块先过滤再转DataFrame
这种方法是真·读取前过滤,完全不会把无效行加载到内存里,内存效率拉满,特别适合大文件。
import csv import pandas as pd # 打开目标CSV文件 with open('your_data.csv', 'r') as f: # 用DictReader读取,自动识别表头 csv_reader = csv.DictReader(f) # 只保留Valid列值为"Yes"的行 filtered_rows = [row for row in csv_reader if row['Valid'] == 'Yes'] # 把过滤后的行转成Pandas DataFrame df = pd.DataFrame(filtered_rows) # 记得把数据类型转对:Value转数值,Date转日期 df['Value'] = pd.to_numeric(df['Value']) df['Date'] = pd.to_datetime(df['Date'], format='%d/%m/%Y')
备选方案:用pandas.read_csv的skiprows参数
如果想直接用Pandas的API实现,可以借助skiprows的函数参数,让它跳过不符合条件的行。不过要注意,这个方法会多次读取文件(每判断一行都要读一次),大文件下效率不如第一种,但代码更紧凑。
import csv import pandas as pd def should_skip_row(row_idx): # 表头行(索引0)不跳过 if row_idx == 0: return False # 读取当前行的Valid列值,判断是否要跳过 with open('your_data.csv', 'r') as f: reader = csv.reader(f) for idx, row in enumerate(reader): if idx == row_idx: # 如果Valid不是"Yes"就跳过 return row[2] != 'Yes' return True # 读取时自动跳过无效行,同时解析日期 df = pd.read_csv('your_data.csv', skiprows=should_skip_row, parse_dates=['Date'], dayfirst=True)
超大型文件折中方案:分块读取+过滤
如果文件大到连csv模块一次加载都吃力,可以用Pandas的分块读取功能,每次读一小部分,过滤后再合并。虽然不是完全的“读取前”过滤,但比读完整文件后过滤省内存多了。
import pandas as pd filtered_chunks = [] # 每次读取1000行,可根据内存调整chunksize for chunk in pd.read_csv('your_data.csv', chunksize=1000, parse_dates=['Date'], dayfirst=True): # 过滤当前块中Valid为"Yes"的行 valid_chunk = chunk[chunk['Valid'] == 'Yes'] filtered_chunks.append(valid_chunk) # 合并所有过滤后的块 df = pd.concat(filtered_chunks, ignore_index=True)
总结
如果追求最高效率和最少内存占用,第一种方法是最优解——完全在读取阶段就过滤掉无效行,不会浪费资源加载不需要的数据。只有当你特别依赖Pandas原生API,或者文件极小的时候,才考虑后面的方案。
内容的提问来源于stack exchange,提问作者A.DS
相关产品推荐
相关产品推荐

