从大型CSV信号文件提取指定时间区间数据的问题排查
问题梳理与代码优化方案
嘿,我来帮你理清楚这个问题,顺便给你的代码做些优化——你已经找到大时间区间无输出的核心原因:Excel打开超大CSV时会截断数据,导致你误以为目标时间区间有数据,但原始文件里其实没有,这属于操作失误而非代码逻辑的致命问题。不过你的代码还有不少可以优化的地方,能让它处理800万行的大文件更高效、更健壮。
原代码的潜在问题
- 浮点数相等比较的精度风险:直接用
float(row[0]) == float(start)匹配起始时间,容易因为浮点数存储的精度误差错过起始点 - 频繁IO操作拖慢效率:把文件写入操作放在循环内部,每次写epoch都打开/关闭文件,对大文件来说会严重拖慢速度
- 未处理表头:如果你的CSV第一行是
time/signal表头,原代码会把表头当成数据行处理,引发错误 - 无意义的全文件遍历:为了找到大起始时间点,需要从头遍历几百万行,效率极低
优化后的代码
import csv def extract_epochs(filename, new_file, start, stop, label): # 计算0.5秒对应的采样点数(10ms/点 → 50点/epoch) samples_per_epoch = 50 # 提前转换为浮点数,避免重复转换 start_time = float(start) stop_time = float(stop) # 一次性打开读写文件,避免频繁IO with open(filename, 'r', newline='') as file_read, open(new_file, 'a', newline='') as file_write: reader = csv.reader(file_read) writer = csv.writer(file_write) # 跳过表头(如果CSV没有表头,直接注释掉这行) next(reader) current_epoch = [] in_target_range = False for row in reader: try: current_time = float(row[0]) signal_val = row[1] except (ValueError, IndexError): # 跳过格式错误的行,避免脚本崩溃 continue # 判断是否进入目标时间区间 if not in_target_range: if current_time >= start_time: in_target_range = True else: continue # 没到起始时间,直接跳过 # 超出结束时间就终止循环,不用遍历整个文件 if current_time >= stop_time: break # 收集当前epoch的采样点 current_epoch.append(signal_val) # 攒够50个点就写入CSV,并重置列表 if len(current_epoch) == samples_per_epoch: current_epoch.append(label) writer.writerow(current_epoch) current_epoch = [] # 可选:处理最后一个不完整的epoch(如果需要保留的话) # if current_epoch: # # 用空值补全到50个点,再写入 # current_epoch.extend([''] * (samples_per_epoch - len(current_epoch))) # current_epoch.append(label) # writer.writerow(current_epoch) # 调用示例 extract_epochs('SC4001E0-PSG_FPZ-CZ.csv', 'new.csv', 0, 1, 0) extract_epochs('SC4001E0-PSG_FPZ-CZ.csv', 'new.csv', 30630, 30750, 1)
优化点说明
- 规避浮点数精度问题:用
current_time >= start_time代替相等比较,避免因小数存储误差错过起始点 - 提升IO效率:只打开一次读写文件,避免循环内频繁的文件操作
- 表头兼容:添加了跳过表头的逻辑,适配标准CSV格式
- 提前终止遍历:当时间超出结束区间时直接break,不用遍历整个800万行文件
- 错误容错:捕获格式错误的行,避免脚本中途崩溃
- 逻辑更清晰:用
in_target_range标记是否进入目标区间,代码可读性更强
额外实用建议
- 不要用Excel打开超大CSV,推荐用VS Code、Notepad++或者专门的大文件查看工具(比如Large Text File Viewer),避免数据截断
- 如果需要频繁提取不同时间区间,可以考虑将CSV转换成Parquet或HDF5格式,这类格式支持按列索引和快速切片,处理大文件的效率远高于纯CSV
内容的提问来源于stack exchange,提问作者C. Mir
相关产品推荐
相关产品推荐

