我正在使用 xarray 从 s3 存储桶读取 ZARR 文件。我成功地按时间和纬度/经度过滤:
def read_zarr(self, dataset: str, region: Region) -> Any:
# Read ZARR from s3 bucket
fs = s3fs.S3FileSystem(key="KEY", secret="SECRET")
mapper = fs.get_mapper(f"{self.S3_PATH}{dataset}")
zarr_ds = xr.open_zarr(mapper, decode_times=True)
# Filter by time
time_period = pd.date_range("2013-01-01", "2023-01-31")
zarr_ds = zarr_ds.sel(time=time_period)
# Filter by latitude/longitude
region_gdf = region.geo_data_frame
latitude_slice = slice(region_gdf.bounds.miny[0], region_gdf.bounds.maxy[0])
longitude_slice = slice(region_gdf.bounds.minx[0], region_gdf.bounds.maxx[0])
return zarr_ds.sel(latitude=latitude_slice, longitude=longitude_slice)
问题在于,这会返回一个矩形数据(如果我们考虑时间维度,实际上是一个长方体)。对于又长又薄的地理区域来说,这将是一种巨大的浪费,因为我将首先下载多年的数据,然后丢弃其中的大部分。以加利福尼亚州为例:
我想将 ZARR 坐标与区域坐标相交。我怎样才能实现它?
一种选择是使用
rioxarray
,然后剪辑到您的区域,与 此线程非常相似。
您需要设置坐标系。假设您的数据以标准纬度/经度给出,则为 epsg 4326(请参阅开头句子此处)。您可能需要使用
region_gdf.to_crs('epsg:4326')
来确保坐标系相同(如果还没有坐标参考系,则使用 set_crs
)。
格式化完成后,您可以使用
rio.clip
方法并设置drop=True
仅保留该区域中的点。
下面的新行 - 它可能无法完全按照编写的方式工作,因为我无法测试它,但我认为它应该让您接近。
import rioxarray
zarr_ds.rio.set_spatial_dims(x_dim="lon", y_dim="lat", inplace=True)
zarr_ds.rio.write_crs("epsg:4326", inplace=True)
zarr_ds_clipped = zarr_ds.rio.clip(region_gdf, drop=True)