Python中有没有更高效的tif文件转换为Stata数据集的方法?
优化方案
原代码的核心性能损耗来自冗余磁盘IO操作:将栅格转换为xyz中间文件写入磁盘、再读取xyz文本文件的过程,在处理2.5m分辨率的大体积tif时,会产生数GB甚至数十GB的临时文件读写开销,占总耗时的90%以上;同时文本格式的xyz解析效率极低,进一步拉长了运行时间。
具体优化措施
- 砍掉中间文件,直接从GDAL内存对象读取数据:不需要调用
gdal.Translate生成xyz文件,直接通过GDAL的API获取栅格的坐标变换参数、读取栅格值数组,在内存中直接生成坐标网格,全程无冗余磁盘IO开销,速度可提升10倍以上。 - 优化数据类型减少读写开销:针对气象数据的精度需求,将坐标、数值列指定为
float32而非默认的float64,内存占用直接减半,写入Stata文件的速度也会大幅提升。 - 多进程并行处理多文件:如果需要批量处理多个tif文件,使用多进程并行调用,充分利用CPU多核性能,处理n个文件的时间可以压缩到单进程的1/n左右。
- 移除不必要的冗余操作:去掉循环内的文件打印、逐个删除临时文件的逻辑,所有临时操作放在内存中完成,不需要额外的磁盘删除操作。
优化后代码示例
from osgeo import gdal import pandas as pd import numpy as np import glob import os # 批量处理多文件需要用到并行库,单文件处理可以不用 from concurrent.futures import ProcessPoolExecutor def tif_to_dta(tif_path): # 只读打开tif,开销更低 ds = gdal.Open(tif_path, gdal.GA_ReadOnly) # 获取栅格尺寸参数 x_size = ds.RasterXSize y_size = ds.RasterYSize # 坐标变换参数:(左上角x, x方向分辨率, 旋转, 左上角y, 旋转, y方向分辨率(通常为负)) geotrans = ds.GetGeoTransform() # 读取栅格值数组并展平为一维 arr = ds.GetRasterBand(1).ReadAsArray().flatten() # 及时释放数据集内存 ds = None # 生成所有网格点的x坐标(取像素中心坐标) x_coords = geotrans[0] + np.arange(x_size) * geotrans[1] + geotrans[1]/2 # 生成所有网格点的y坐标(取像素中心坐标) y_coords = geotrans[3] + np.arange(y_size) * geotrans[5] + geotrans[5]/2 # 生成二维坐标网格后展平 x_grid, y_grid = np.meshgrid(x_coords, y_coords) x_flat = x_grid.flatten() y_flat = y_grid.flatten() # 直接生成DataFrame,指定数据类型节省内存和写入时间 df = pd.DataFrame({ "_CX": x_flat.astype("float32"), "_CY": y_flat.astype("float32"), "tmin": arr.astype("float32") }) # 写入Stata文件,指定高版本格式提升写入速度 df.to_stata(f"{os.path.splitext(tif_path)[0]}.dta", write_index=False, version=118) # 如果需要处理完删除原tif可取消下面注释 # os.remove(tif_path) return f"{tif_path} 处理完成" if __name__ == "__main__": tif_list = glob.glob("*.tif") # 单文件/少量文件处理用下面的串行逻辑即可 # for tif in tif_list: # print(tif_to_dta(tif)) # 多文件批量处理用多进程并行,max_workers填你的CPU核心数即可 with ProcessPoolExecutor(max_workers=8) as executor: for res in executor.map(tif_to_dta, tif_list): print(res)
优化后单张2.5m分辨率tif的处理时间可从1.5小时压缩到10分钟以内,批量多文件并行的话速度提升更明显。
内容的提问来源于stack exchange,提问作者Jared Greathouse
相关产品推荐
相关产品推荐

