使用 xarray 更改坐标系以进行切片操作

Posted

技术标签:

【中文标题】使用 xarray 更改坐标系以进行切片操作【英文标题】:Using xarray to change coordinate system in order to Slice operation 【发布时间】:2019-08-07 16:31:00 【问题描述】:

我是新来的。 首先,我非常感谢您的时间和考虑。 关于在 python 中管理 2 个不同的 netcdf 文件,我有 2 个问题。 我搜索了很多,但不幸的是我找不到解决方案。

1- 我有一个 netcdf 文件,其坐标如下:

time     datetime64[ns] 2016-08-16T22:00:00
* y        (y) int32 220000  ...  620000
* x        (x) int32 20000  ...  720000
 lat      (y, x) float64 dask.array<shape=(401, 701), 
 lon      (y, x) float64 dask.array<shape=(401, 701),

我需要将坐标更改为 lon/lat,以便我可以根据特定的 lon/lat 坐标(通过使用 xarray)对区域进行切片。但我不知道如何将 x 和 y 更改为 lon lat。 这是我的代码:

import xarray as xr
import matplotlib.pyplot as plt
p = "R_201608.nc"
ds = xr.open_mfdataset(p)
q=ds.RR.sel(time='2016-08-16T21:00:00')

2- 与 1 类似,我有另一个 netcdf 文件,其坐标如下:

   * X           (X) float32 557600.0 .. 579400.0
   * Y           (Y) float32 5190600 ... 5205400.0
   * time        (time) datetime64[ns] 2007-01I

如何将 x 和 y 转换为 lon/lat 系统以便我可以在 lon/lat 系统中绘制它?

与@Ryan 相关的编辑: 1-是的。该文件展示了大面积的降雨量。我想将它切割成更小的区域 - 与 q2 相关的文件的类似区域 - 并使用偏差、RMSE 等进行比较。这里是与此文件相关的完整信息:

 <xarray.Dataset>
  Dimensions:                  (time: 2976, x: 701, y: 401)
  Coordinates:
  * time             (time) datetime64[ns] 2016-08-31T23:45:00
  * y          (y) int32 220000 221000  ... 619000 620000
  * x          (x) int32 20000 21000  ... 719000 720000
  lat        (y, x) float64 dask.array<shape=(401, 701),chunksize=(401, 701)>
  lon        (y, x) float64 dask.array<shape=(401, 701), chunksize=(401, 701)

 Data variables:
    RR       (time, y, x) float32 dask.array<shape=(2976, 401, 701),    chunksize=(2976, 401, 701)>
    lambert_conformal_conic  int32 ...

    Conventions:  CF-1.5

与@Ryan 相关的编辑:2- 这是有关第二个文件(较小区域)的完整信息:

   <xarray.DataArray 'Precip' (time: 8928, Y: 75, X: 110)>
   dask.array<shape=(8928, 75, 110), dtype=float32, chunksize=(288, 75, 110)>
   Coordinates:

      sensor_height_precip  float32 1.5
      sensor_height_P       float32 1.5
      * X                     (X) float32 557600.0 557800.0 ... 579200.0 579400.0
      * Y                     (Y) float32 5190600.0 5190800.0 ... 5205400.0
      * time                  (time) datetime64[ns]  2007-01-31T23:55:00
   Attributes:
      grid_mapping:         UTM33N
      ancillary_variables:  QFlag_Precip QGrid_Precip
      long_name:            Precipitation Amount
      standard_name:        precipitation_amount
      cell_methods:         time:sum
      units:                mm

【问题讨论】:

您可以使用pyproj 转换坐标(您的第二个问题)。您的投影示例是here。 非常感谢,巴特。我阅读了示例并进行了很多搜索,但是由于我的文件是多维的(x,y,t,rain),因此无法进行转换。 我想我没有很好地解释这个问题。我有两个不同的 netcdf 文件,它们具有不同的协调系统和不同的网格大小(我在上面描述过)。我需要更改坐标系,以便我可以重新调整其中一个坐标系,然后使用一些统计指数(比如说,偏差 RMSE ...)来比较它们。 【参考方案1】:

在问题 1) 中,无法将 lon 和 lat 转换为维度坐标,因为它们是二维的(都有维度 x、y)。用于切片的维度坐标只能是一维的。如果您可以更具体地确定切片后想要做什么,我们可以提供更多关于如何进行的建议。是否要选择一个特定的纬度/经度范围,然后计算一些统计数据(例如均值/方差)?

在问题 2) 中,您似乎有地图投影。如果没有有关投影的更多信息,就不可能转换为纬度/经度坐标或在地图上绘图。您的数据集中是否包含有关使用的地图投影的更多信息?你能发布print(ds)的完整输出吗?

【讨论】:

哇,真快!非常感谢。我在我的问题中添加了一个版本。非常感谢。【参考方案2】:

在您的帮助下,我已经解决了我的问题。非常感谢。 正如@Bart 提到的,我可以使用 PYPROJ 将两个数据集的坐标更改为 lon/lat。从原始坐标和投影坐标创建 meshgid 是关键。

from pyproj import Proj
nxv,  nyv = np.meshgrid(nx, ny)       
unausp = Proj('+proj=lcc +lat_1=49 +lat_2=46 +lat_0=47.5   +lon_0=13.33333333333333 +x_0=400000 +y_0=400000 +ellps=bessel    +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m +no_defs ')   
nlons, nlats = unausp(nxv, nyv, inverse=True)                                 
upLon,  upLat = np.meshgrid(nlons,nlats)

由于我想比较两个具有不同空间分辨率(不同网格大小)的降雨数据集,我必须使用 xarray 插值来放大其中一个:

upnew_lon = np.linspace(w.X[0], w.X[-1], w.dims['X'] // 5) 
upnew_lat = np.linspace(w.Y[0], w.Y[-1], w.dims['Y'] //5) 
uppds = w.interp(Y=upnew_lat, X=upnew_lon)  

据我所知,这种插值是基于线性插值的。我将放大的数据集与原始数据集进行了比较。升级后平均降雨量减少约 0.03 毫米/天。我只是想知道你认为这种次小时降雨量的升级方法是否可靠?

【讨论】:

以上是关于使用 xarray 更改坐标系以进行切片操作的主要内容,如果未能解决你的问题,请参考以下文章

xarray 使用教程 - 未完待续

xarray 自动将 _FillValue 应用于 netCDF 输出上的坐标

如何将多个csv连接到xarray并定义坐标?

Python气象数据处理进阶之Xarray(5):数据整合(分组,合并...)

使用坐标剪切/切片图像

xarray 笔记:DataArray