【问题标题】:Regridding coordinates with Python-Xarray使用 Python-Xarray 重新网格化坐标
【发布时间】:2019-04-06 20:19:22
【问题描述】:

我有一个 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”,因为它们链接到 Datavariable “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 的理解会很有帮助?

【问题讨论】:

    标签: python netcdf python-xarray


    【解决方案1】:

    有一个原则可以解释为什么您的两种初始方法都不起作用。在Dataset 中,变量具有沿坐标的值。坐标在Dataset 中与变量分开存在。您可能有三个变量UVW,它们都沿数据集中的某个坐标longitude 变化。 UVlongitude 值以不同的顺序排列是可以的,但在数据集中它们必须具有相同的顺序。

    当您将变量分配给数据集已经具有变量坐标的数据集时,xarray 将自动重新排序该变量以具有与数据集相同的顺序。它还会做一些好事,比如在变量没有数据集中给定坐标的值的地方添加 nan 值。

    这是一个例子,我制作了一个DatasetDataArray,它们都有一个经度坐标,但方向相反。当我将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 ...
    

    【讨论】:

    • 谢谢,我很困惑,因为文档说坐标没有存储为有序字典,这让我相信每个变量都通过字典单独链接到坐标。当然,现在我在一个没有意义的数据集中看到了这一点
    【解决方案2】:

    这不是python解决方案,但如果你在linux上并且有nco你可以输入

    ncap2 -O -s 'where(lon>180) lon=lon-360' ifile ofile
    

    按照这里的答案How to change longitude range in a NetCDF

    【讨论】:

    • 当然,正如我在帖子开头所承认的那样,但也许 OP(或其他正在寻找此问题的解决方案的人,但可能不会与 python 结合)不知道有一个班轮外壳替代品-我认为在python答案列表(我赞成)中添加一个简短的有效替代品并没有什么害处,因此永远不明白为什么SO上的人会否决解决问题但不在请求的语言。答案不仅适用于 OP,也适用于广大社区。​​span>
    • 当然,我也很高兴知道这种方式也是可能的。对于更大的数据集,我假设在 nco 中执行此操作会比在 python 中更快?
    • 嗨 light_B,感谢您的积极评价。如果您想打开文件,更改范围,然后在 python 中进行进一步处理,在 python 中可能会更快,因为使用 nco/cdo 解决方案,您正在打开、读取、写入磁盘,然后您将再次打开并读取在 python 中进行处理。如果您想进行一次更改,然后重复使用该文件,那么这样做可能更有效。老实说,我不是专家。但是,就您的时间而言,nco/cdo 解决方案通常总是更有效,这通常更重要;-)
    【解决方案3】:

    我为单线道歉,但这正是我解决此问题的方法: d = d.assign_coords(longitude=(((d.longitude + 180) % 360) - 180)).sortby('longitude') 你应该在Dataset 级别而不是DataArray 工作。

    【讨论】:

    • 感谢您的建议。如果我的数据中有其他坐标,例如纬度或压力水平,那么使用 dataset.assign_coords 会自动删除其他坐标并仅将经度分配为新坐标吗?
    • 在 xarray 文档中,您可以阅读 assign_coords:“除了新坐标之外,还返回一个包含所有原始数据的新对象。”。然后,其他坐标不会改变,在这种特定情况下,您只需用修改后的版本“覆盖”经度...
    【解决方案4】:

    cdo 可以快速解决这些问题, 喜欢:

    cdo sellonlatbox,-180,180,-90,90 a.nc b.nc
    

    a.nc 是你的数据,b.nc 是你想要的结果。

    【讨论】:

      猜你喜欢
      • 2020-04-27
      • 1970-01-01
      • 2019-01-17
      • 1970-01-01
      • 2017-06-08
      • 2017-03-25
      • 2020-10-20
      • 2021-12-12
      • 2019-01-07
      相关资源
      最近更新 更多