我正在尝试获取一个人口光栅,并对其进行重新采样和重新投影,以匹配降水光栅的形状和分辨率。
数据链接:人口数据:https://figshare.com/ndownloader/files/10257111Precipitation数据:https://www.ncei.noaa.gov/data/nclimgrid-monthly/access/nclimgrid_prcp.nc
人口数据是覆盖美国大陆的5个不同人口模型的每十年一系列栅格。如果你只需选择其中一个栅格,我就可以计算出其余的栅格(无论如何,我已经组合成一个多频带栅格)。例如,如果使用pop_m4_2010光栅将有所帮助。分辨率为1x1km,投影为阿尔伯斯等面积圆锥NAD 83 ESRI:102003。
降水数据是涵盖美国大陆月降水数据的netcdf文件。分辨率为5x5km,投影为WGS84 EPSG:4326。
我使用以下代码将netcdf转换为tiff:
import xarray as xr import rioxarray as rio prcp_file = xr.open_dataset('nclimgrid_prcp.nc') prp = prcp_file['prcp'] prp = prp.rio.set_spatial_dims(x_dim='lon', y_dim='lat') prp.rio.write_crs("epsg:4326", inplace=True) prp.rio.to_raster('prp_raster.tiff')
我还使用QGIS打开填充文件(添加光栅层,导航到pop_m4_2010的下载文件夹并选择“w001001.adf”文件)。当我在WGS84项目中这样做时,QGIS会自动显示为强制重新投影,但我是新手,所以我不确定它是否正确。
从这一点开始,我尝试了几种方法来重新采样人口光栅,以匹配降水光栅的5x5分辨率。
- 在QGIS处理工具箱GRASS r.resample
- 中QGIS处理工具包Raster Layer Zonal Statistics
- 在Python中,老实说,我已经忘记了我在GDAL.Warp、Rasterio.Warp、仿射变换、rio.reproject_match等上关注的所有不同论坛帖子和教程。下面是一些代码尝试的示例
其中许多似乎都有效(尤其是rio.reproject_match似乎简单有效。然而,这些似乎都没有达到预期效果。当我通过传递县矢量形状文件的分区统计数据来测试生成的人口栅格的准确性时,该区域的人口总数要么为0,要么非常不准确。
我做错了什么?
重新投影匹配(_M):
import rioxarray # for the extension to load import xarray import matplotlib.pyplot as plt %matplotlib inline def print_raster(raster): print( f"shape: {raster.rio.shape}\n" f"resolution: {raster.rio.resolution()}\n" f"bounds: {raster.rio.bounds()}\n" f"sum: {raster.sum().item()}\n" f"CRS: {raster.rio.crs}\n" ) xds = rioxarray.open_rasterio('pop_m4_2010.tif') xds_match = rioxarray.open_rasterio('prp_raster.tiff') fig, axes = plt.subplots(ncols=2, figsize=(12,4)) xds.plot(ax=axes[0]) xds_match.plot(ax=axes[1]) plt.draw() print("Original Raster:\n----------------\n") print_raster(xds) print("Raster to Match:\n----------------\n") print_raster(xds_match) xds_repr_match = xds.rio.reproject_match(xds_match) print("Reprojected Raster:\n-------------------\n") print_raster(xds_repr_match) print("Raster to Match:\n----------------\n") print_raster(xds_match) xds_repr_match.rio.to_raster("reproj_pop.tif")
Rasterio的另一种方式。扭曲:
import rasterio from rasterio.warp import calculate_default_transform, reproject, Resampling #open source raster srcRst =rasterio.open('pop_m4_2010.tif') print("source raster crs:") print(srcRst.crs) dstCrs = {'init': 'EPSG:4326'} print("destination raster crs:") print(dstCrs) #calculate transform array and shape of reprojected raster transform, width, height = calculate_default_transform( srcRst.crs, dstCrs, srcRst.width, srcRst.height, *srcRst.bounds) print("transform array of source raster") print(srcRst.transform) print("transform array of destination raster") print(transform) #working of the meta for the destination raster kwargs = srcRst.meta.copy() kwargs.update({ 'crs': dstCrs, 'transform': transform, 'width': width, 'height': height }) #open destination raster dstRst = rasterio.open('pop_m4_2010_reproj4326.tif', 'w', **kwargs) #reproject and save raster band data for i in range(1, srcRst.count + 1): reproject( source=rasterio.band(srcRst, i), destination=rasterio.band(dstRst, i), #src_transform=srcRst.transform, src_crs=srcRst.crs, #dst_transform=transform, dst_crs=dstCrs, resampling=Resampling.bilinear) print(i) #close destination raster dstRst.close()
这里是Rasterio的第二次尝试。Warp:
import rasterio from rasterio.warp import calculate_default_transform, reproject, Resampling prcp = rasterio.open('prp_raster.tiff', mode = 'r') with rasterio.open('pop_m4_2010.tif') as dataset: # resample data to target shape data = dataset.read(out_shape=(dataset.count,prcp.height,prcp.width), resampling=Resampling.bilinear) # scale image transform transform = dataset.transform * dataset.transform.scale((dataset.width / data.shape[-1]), (dataset.height / data.shape[-2])) # Register GDAL format drivers and configuration options with a # context manager. with rasterio.Env(): profile = src.profile profile.update( dtype=rasterio.float32, count=1, compress='lzw') with rasterio.open('pop_m4_2010_resampledtoprcp.tif', 'w', **profile) as dst: dst.write(data.astype(rasterio.float32))