使用 Python-Xarray 重新网格化坐标
Regridding coordinates with Python-Xarray
我有一个 NetCDF 文件,其中变量存储在 0 到 360 度经度内。我想将它转换为 -180 到 180 度。这应该是一项相当简单的任务,但出于某种原因,我似乎无法完成教程中给出的一些示例。
ds = xr.open_dataset(file_)
>ds
<xarray.Dataset>
Dimensions: (lev: 1, lon: 720, time: 1460)
Coordinates:
* lon (lon) float64 0.0 0.5 1.0 1.5 2.0 2.5 ... -2.5 -2.0 -1.5 -1.0 -0.5
* lev (lev) float32 1.0
* time (time) datetime64[ns] 2001-01-01 ... 2001-12-31T18:00:00
Data variables:
V (time, lev, lon) float32 13.281297 11.417505 ... -19.312767
我尝试使用 Dataset.assign_coord
的帮助
ds.V.assign_coords(lon=((ds.V.lon + 180) % 360 - 180))
#gives me a new array with lon -180 to 180
ds['V'] = ds.V.assign_coords(lon=((ds.V.lon + 180) % 360 - 180))
# didn't modify the V for some reason?
所以,assign_coords可以,但是将变量设置回Dataset就不行了。经过多次尝试,我想直接修改坐标"lon" 因为它们通过字典链接到数据变量 "V"。
ds.coords['lon'] = (ds.coords['lon'] + 180) % 360 - 180
#solves the problem!
第二个问题 我遇到的是根据上面修改的经度对我的数据变量进行排序。我试过了
ds['V'] = ds.V.sortby(ds.lon)
>ds.V
# the array is not sorted according to -180 to 180 values
但是当我对数据集进行排序并分配它时,它起作用了。
ds = ds.sortby(ds.lon) # now my dataset is sorted to -180 to 180 degrees lon
如果有人能指出为什么我对这两个问题的第一种方法不起作用,那将对我理解 xarrays 非常有帮助?
有一个原则可以解释为什么您最初的两种方法都不起作用。在 Dataset
中,变量具有沿坐标的值。坐标在 Dataset
中与变量分开存在。您可能有三个变量 U
、V
和 W
,它们都沿着数据集中的某个坐标 longitude
变化。对于 U
和 V
来说,它们的 longitude
值的顺序不同是可以的,但在数据集中它们必须具有相同的顺序。
当您将变量分配给数据集已有变量坐标的数据集时,xarray
将自动重新排序该变量,使其与数据集具有相同的顺序。它还会做一些很好的事情,比如在变量没有数据集中给定坐标值的地方添加 nan
值。
这是一个示例,其中我制作了一个 Dataset
和 DataArray
,它们都具有经度坐标,但方向相反。当我将DataArray
赋值给Dataset
时,坐标会自动反转。
In[17]: ds
Out[17]:
<xarray.Dataset>
Dimensions: (longitude: 10)
Coordinates:
* longitude (longitude) float64 360.0 320.0 280.0 240.0 200.0 160.0 120.0 ...
Data variables:
*empty*
In [18]: da
Out[18]:
<xarray.DataArray (longitude: 10)>
array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
Coordinates:
* longitude (longitude) float64 0.0 40.0 80.0 120.0 160.0 200.0 240.0 ...
In [19]: ds['v'] = da
In [20]: ds['v']
Out[20]:
<xarray.DataArray 'v' (longitude: 10)>
array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
Coordinates:
* longitude (longitude) float64 360.0 320.0 280.0 240.0 200.0 160.0 120.0 ...
这是一个类似的例子,它会自动添加 nan
:
In [27]: ds
Out[27]:
<xarray.Dataset>
Dimensions: (longitude: 10)
Coordinates:
* longitude (longitude) float64 360.0 320.0 280.0 240.0 200.0 160.0 120.0 ...
Data variables:
*empty*
In [28]: da
Out[28]:
<xarray.DataArray (longitude: 3)>
array([ 0., 0., 0.])
Coordinates:
* longitude (longitude) float64 0.0 40.0 80.0
In [29]: ds['v'] = da
In [30]: ds['v']
Out[30]:
<xarray.DataArray 'v' (longitude: 10)>
array([ nan, nan, nan, nan, nan, nan, nan, 0., 0., 0.])
Coordinates:
* longitude (longitude) float64 360.0 320.0 280.0 240.0 200.0 160.0 120.0 ...
这不是 python 解决方案,但如果你在 linux 上并且有 nco,你可以输入
ncap2 -O -s 'where(lon>180) lon=lon-360' ifile ofile
根据这里的回答 How to change longitude range in a NetCDF
我为单行道歉,但这正是我解决这个问题的方法:
d = d.assign_coords(longitude=(((d.longitude + 180) % 360) - 180)).sortby('longitude')
你应该在 Dataset
级别而不是 DataArray
级别工作。
cdo 可以快速解决这些问题,
喜欢:
cdo sellonlatbox,-180,180,-90,90 a.nc b.nc
a.nc是你的数据,b.nc是你想要的结果。
我有一个 NetCDF 文件,其中变量存储在 0 到 360 度经度内。我想将它转换为 -180 到 180 度。这应该是一项相当简单的任务,但出于某种原因,我似乎无法完成教程中给出的一些示例。
ds = xr.open_dataset(file_)
>ds
<xarray.Dataset>
Dimensions: (lev: 1, lon: 720, time: 1460)
Coordinates:
* lon (lon) float64 0.0 0.5 1.0 1.5 2.0 2.5 ... -2.5 -2.0 -1.5 -1.0 -0.5
* lev (lev) float32 1.0
* time (time) datetime64[ns] 2001-01-01 ... 2001-12-31T18:00:00
Data variables:
V (time, lev, lon) float32 13.281297 11.417505 ... -19.312767
我尝试使用 Dataset.assign_coord
的帮助ds.V.assign_coords(lon=((ds.V.lon + 180) % 360 - 180))
#gives me a new array with lon -180 to 180
ds['V'] = ds.V.assign_coords(lon=((ds.V.lon + 180) % 360 - 180))
# didn't modify the V for some reason?
所以,assign_coords可以,但是将变量设置回Dataset就不行了。经过多次尝试,我想直接修改坐标"lon" 因为它们通过字典链接到数据变量 "V"。
ds.coords['lon'] = (ds.coords['lon'] + 180) % 360 - 180
#solves the problem!
第二个问题 我遇到的是根据上面修改的经度对我的数据变量进行排序。我试过了
ds['V'] = ds.V.sortby(ds.lon)
>ds.V
# the array is not sorted according to -180 to 180 values
但是当我对数据集进行排序并分配它时,它起作用了。
ds = ds.sortby(ds.lon) # now my dataset is sorted to -180 to 180 degrees lon
如果有人能指出为什么我对这两个问题的第一种方法不起作用,那将对我理解 xarrays 非常有帮助?
有一个原则可以解释为什么您最初的两种方法都不起作用。在 Dataset
中,变量具有沿坐标的值。坐标在 Dataset
中与变量分开存在。您可能有三个变量 U
、V
和 W
,它们都沿着数据集中的某个坐标 longitude
变化。对于 U
和 V
来说,它们的 longitude
值的顺序不同是可以的,但在数据集中它们必须具有相同的顺序。
当您将变量分配给数据集已有变量坐标的数据集时,xarray
将自动重新排序该变量,使其与数据集具有相同的顺序。它还会做一些很好的事情,比如在变量没有数据集中给定坐标值的地方添加 nan
值。
这是一个示例,其中我制作了一个 Dataset
和 DataArray
,它们都具有经度坐标,但方向相反。当我将DataArray
赋值给Dataset
时,坐标会自动反转。
In[17]: ds
Out[17]:
<xarray.Dataset>
Dimensions: (longitude: 10)
Coordinates:
* longitude (longitude) float64 360.0 320.0 280.0 240.0 200.0 160.0 120.0 ...
Data variables:
*empty*
In [18]: da
Out[18]:
<xarray.DataArray (longitude: 10)>
array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
Coordinates:
* longitude (longitude) float64 0.0 40.0 80.0 120.0 160.0 200.0 240.0 ...
In [19]: ds['v'] = da
In [20]: ds['v']
Out[20]:
<xarray.DataArray 'v' (longitude: 10)>
array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
Coordinates:
* longitude (longitude) float64 360.0 320.0 280.0 240.0 200.0 160.0 120.0 ...
这是一个类似的例子,它会自动添加 nan
:
In [27]: ds
Out[27]:
<xarray.Dataset>
Dimensions: (longitude: 10)
Coordinates:
* longitude (longitude) float64 360.0 320.0 280.0 240.0 200.0 160.0 120.0 ...
Data variables:
*empty*
In [28]: da
Out[28]:
<xarray.DataArray (longitude: 3)>
array([ 0., 0., 0.])
Coordinates:
* longitude (longitude) float64 0.0 40.0 80.0
In [29]: ds['v'] = da
In [30]: ds['v']
Out[30]:
<xarray.DataArray 'v' (longitude: 10)>
array([ nan, nan, nan, nan, nan, nan, nan, 0., 0., 0.])
Coordinates:
* longitude (longitude) float64 360.0 320.0 280.0 240.0 200.0 160.0 120.0 ...
这不是 python 解决方案,但如果你在 linux 上并且有 nco,你可以输入
ncap2 -O -s 'where(lon>180) lon=lon-360' ifile ofile
根据这里的回答 How to change longitude range in a NetCDF
我为单行道歉,但这正是我解决这个问题的方法:
d = d.assign_coords(longitude=(((d.longitude + 180) % 360) - 180)).sortby('longitude')
你应该在 Dataset
级别而不是 DataArray
级别工作。
cdo 可以快速解决这些问题, 喜欢:
cdo sellonlatbox,-180,180,-90,90 a.nc b.nc
a.nc是你的数据,b.nc是你想要的结果。