如何比列表推导式更快将多份CSV转为Polars DataFrame?
高效批量读取Google Drive中CSV文件到Polars DataFrame的方案
核心问题分析
单线程逐个读取大量CSV文件,加上Google Drive的网络IO延迟,是导致耗时超30分钟的主要原因。以下是几个高效且Pythonic的解决方案:
方案1:多线程并行读取(IO密集型任务最优)
读取文件属于IO密集型操作,使用线程池可以同时处理多个文件的读取请求,大幅减少等待IO的时间。
from concurrent.futures import ThreadPoolExecutor import polars as pl def read_sim_csv(path): return pl.read_csv(path, schema_overrides={"X0.6": pl.Float64}) def read_ens_csv(path): return pl.read_csv(path, schema_overrides={"ridge_reg": pl.Float64}) # 线程池大小根据Colab资源调整,建议10-20 with ThreadPoolExecutor(max_workers=15) as executor: bdsim = list(executor.map(read_sim_csv, simpaths)) bdens = list(executor.map(read_ens_csv, enspaths))
方案2:先复制到本地临时磁盘再读取
Colab本地磁盘的读写速度远高于Google Drive的网络IO,先批量复制文件到本地再读取,能显著降低IO延迟影响。
import os from concurrent.futures import ThreadPoolExecutor import polars as pl # 创建本地临时目录 temp_sim_dir = "/tmp/sim_csvs" temp_ens_dir = "/tmp/ens_csvs" os.makedirs(temp_sim_dir, exist_ok=True) os.makedirs(temp_ens_dir, exist_ok=True) # 批量复制Drive文件到本地 def copy_to_local(src_path, dest_dir): dest_path = os.path.join(dest_dir, os.path.basename(src_path)) !cp "$src_path" "$dest_path" return dest_path # 并行复制 with ThreadPoolExecutor(max_workers=15) as executor: local_sim_paths = list(executor.map(lambda p: copy_to_local(p, temp_sim_dir), simpaths)) local_ens_paths = list(executor.map(lambda p: copy_to_local(p, temp_ens_dir), enspaths)) # 从本地读取文件 bdsim = [pl.read_csv(p, schema_overrides={"X0.6": pl.Float64}) for p in local_sim_paths] bdens = [pl.read_csv(p, schema_overrides={"ridge_reg": pl.Float64}) for p in local_ens_paths]
注意:本地临时目录的文件会在Colab会话结束后被删除,若需保留需复制回Google Drive。
方案3:延迟加载+合并(若最终需合并为单个DataFrame)
如果你的目标是将所有文件合并成单个DataFrame,直接使用Polars的scan_csv延迟加载+concat合并,能进一步优化性能,减少内存开销。
import polars as pl # 合并所有sim文件为单个DataFrame combined_sim = pl.concat([ pl.scan_csv(p, schema_overrides={"X0.6": pl.Float64}) for p in simpaths ]).collect() # 合并所有ens文件为单个DataFrame combined_ens = pl.concat([ pl.scan_csv(p, schema_overrides={"ridge_reg": pl.Float64}) for p in enspaths ]).collect()
额外优化建议
- 若CSV文件格式统一,定义完整的schema而非仅覆盖单个字段,避免Polars自动推断字段类型的开销。例如:
sim_schema = {"X0.6": pl.Float64, "col1": pl.Int32, "col2": pl.String} bdsim = [pl.read_csv(p, schema=sim_schema) for p in local_sim_paths] - 调整线程池
max_workers参数,避免过度占用Colab资源,10-20是比较稳妥的范围。
内容的提问来源于stack exchange,提问作者ELOY GARCIA
相关产品推荐
相关产品推荐

