大CSV文件按4位小数匹配查询值的技术问题求助
解决1200万行CSV数据的小数位数匹配问题
我有一个1200万行的CSV文件,需要根据两个4位小数的查询值,匹配文件中对应14位小数的x、y列,返回对应的z值。目前存在两个问题:
- 尝试对列值保留4位小数后匹配的代码报错
- 逐行修改小数位数并保存的代码效率极低(处理10行需1分钟)
问题根源
- 报错原因:原报错代码用Python原生
round()和float()处理Dask DataFrame整列,不符合Dask的向量操作逻辑——Dask需要用自身API对整列做批量处理,不能直接用单值操作函数处理整列。 - 低效原因:逐行循环修改DataFrame是性能最差的方式,Pandas/Dask支持向量化操作,可一次性处理整列,效率能提升几个数量级。
方案1:查询时直接对列做四舍五入匹配(无需修改原数据)
利用Dask的向量化round()方法对x、y列批量处理,直接构建查询条件,无需预处理整个文件,节省时间和存储空间:
import dask.dataframe as dk import time time_start = time.time() df2 = dk.read_parquet('n46_e032_1arc_v3_parquet') # 用Dask的round方法批量处理整列,再匹配目标值 elevation2 = df2[(df2['x'].round(4) == 32.3452) & (df2['y'].round(4) == 46.4567)].compute() print(elevation2) print(f"耗时: {time.time() - time_start:.2f} 秒") elevation2 = elevation2['z'].values[0] print(elevation2)
方案2:预处理数据(批量修改小数位数后保存)
如果需要多次查询,建议先一次性将x、y列批量修改为4位小数,再保存为Parquet(比CSV读写效率高得多),后续查询直接使用预处理后的文件:
import pandas as pd import time filename = 'n46_e032_1arc_v3.csv' time_start = time.time() # 内存足够时用Pandas读取,内存不足则用Dask分块处理 df2 = pd.read_csv(filename) # 向量化操作一次性修改整列,彻底避免循环 df2['x'] = df2['x'].round(4) df2['y'] = df2['y'].round(4) # 保存为Parquet格式,压缩率和读写效率远高于CSV df2.to_parquet('preprocessed_dem.parquet', index=False) print(f"预处理耗时: {time.time() - time_start:.2f} 秒") # 后续查询示例 time_start = time.time() df2 = dk.read_parquet('preprocessed_dem.parquet') elevation2 = df2[(df2['x'] == 32.3452) & (df2['y'] == 46.4567)].compute() print(elevation2['z'].values[0]) print(f"查询耗时: {time.time() - time_start:.2f} 秒")
补充说明
- 若内存不足以一次性加载1200万行数据,用Dask分块处理同样支持向量化操作:
import dask.dataframe as dk df2 = dk.read_csv(filename) df2['x'] = df2['x'].round(4) df2['y'] = df2['y'].round(4) df2.to_parquet('preprocessed_dem_dask.parquet') - Parquet是列式存储格式,支持压缩,比CSV更适合大数据存储,查询时可只加载需要的列,进一步提升效率。
内容的提问来源于stack exchange,提问作者Alejandro
相关产品推荐
相关产品推荐

