【问题标题】:xarray mask outside list of coordinates坐标列表外的 xarray 掩码
【发布时间】:2022-11-17 07:42:41
【问题描述】:

我有一个 Xarray DataArray,其值超过矩形 2D 网格,以及来自 pandas Dataframe 中包含的该网格的任意子集的点列表(坐标值对)。

如何屏蔽掉网格坐标未出现在列表点中的 DataArray 中的值(即设置为 NaN)?

例如考虑 DataArray

In [35]: da = xr.DataArray(data=np.random.randint(10, size=(5, 6)), coords={"x": np.linspace(0, 10, 5), "y": np.linspace(0, 12, 6)})

In [36]: da
Out[36]: 
<xarray.DataArray (x: 5, y: 6)>
array([[6, 0, 2, 3, 9, 8],
       [7, 6, 4, 8, 5, 8],
       [7, 4, 4, 5, 4, 7],
       [9, 8, 8, 1, 8, 0],
       [8, 9, 4, 3, 3, 6]])
Coordinates:
  * x        (x) float64 0.0 2.5 5.0 7.5 10.0
  * y        (y) float64 0.0 2.4 4.8 7.2 9.6 12.0

和数据框

In [44]: coords = pd.DataFrame([[2.5, 4.8], [2.5, 7.2], [5.0, 12.0], [7.5, 7.2], [10.0, 2.4]], columns=["x_coord", "y_coord"])

In [45]: coords
Out[45]: 
   x_coord   y_coord
0      2.5       4.8
1      2.5       7.2
2      5.0      12.0
3      7.5       7.2
4     10.0       2.4

那么我希望输出是:

Out[84]: 
<xarray.DataArray (x: 5, y: 6)>
array([[nan, nan, nan, nan, nan, nan],
       [nan, nan,  4.,  8., nan, nan],
       [nan, nan, nan, nan, nan,  7.],
       [nan, nan, nan,  1., nan, nan],
       [ 8., nan, nan, nan, nan, nan]])
Coordinates:
  * x        (x) float64 0.0 2.5 5.0 7.5 10.0
  * y        (y) float64 0.0 2.4 4.8 7.2 9.6 12.0

【问题讨论】:

    标签: mask netcdf python-xarray


    【解决方案1】:

    您可以通过将 x 和 y 坐标设置为索引,然后使用 to_xarray 将数据帧转换为 xarray 对象。因为你没有留下任何数据,我只分配一个“标志”变量:

    In [20]: flag = (
        ...:     coords.assign(flag=1)
        ...:     .set_index(["x_coord", "y_coord"])
        ...:     .flag
        ...:     .to_xarray()
        ...:     .fillna(0)
        ...:     .rename({"x_coord": "x", "y_coord": "y"})
        ...: )
    
    In [21]: flag
    Out[21]:
    <xarray.DataArray 'flag' (x: 4, y: 4)>
    array([[0., 1., 1., 0.],
           [0., 0., 0., 1.],
           [0., 0., 1., 0.],
           [1., 0., 0., 0.]])
    Coordinates:
      * x        (x) float64 2.5 5.0 7.5 10.0
      * y        (y) float64 2.4 4.8 7.2 12.0
    

    这现在与您的阵列形状相同,可以用作遮罩:

    In [22]: da.where(flag)
    Out[22]:
    <xarray.DataArray (x: 4, y: 3)>
    array([[nan,  7., nan],
           [nan, nan,  5.],
           [nan, nan, nan],
           [ 8., nan, nan]])
    Coordinates:
      * x        (x) float64 2.5 5.0 7.5 10.0
      * y        (y) float64 2.4 4.8 12.0
    

    或者你可以通过重新索引来保留 da 的形状:

    
    In [23]: da.where(flag.reindex_like(da, fill_value=0))
    Out[23]:
    <xarray.DataArray (x: 5, y: 6)>
    array([[nan, nan, nan, nan, nan, nan],
           [nan, nan,  7., nan, nan, nan],
           [nan, nan, nan, nan, nan,  5.],
           [nan, nan, nan, nan, nan, nan],
           [nan,  8., nan, nan, nan, nan]])
    Coordinates:
      * x        (x) float64 0.0 2.5 5.0 7.5 10.0
      * y        (y) float64 0.0 2.4 4.8 7.2 9.6 12.0
    

    以防万一它有用,如果你想做相反的事情;也就是说,在数据框中给定的点处从 DataArray 中提取值,您可以使用 xarray 的 advanced indexing rules 使用 DataArray 索引器从数组中提取特定点:

    In [28]: da.sel(
        ...:     x=coords.x_coord.to_xarray(),
        ...:     y=coords.y_coord.to_xarray(),
        ...:     method="nearest",
        ...:     tolerance=1e-9, # use a (low) tolerance to handle floating-point error
        ...: )
    
    Out[28]:
    <xarray.DataArray (index: 5)>
    array([7, 0, 5, 8, 8])
    Coordinates:
        x        (index) float64 2.5 2.5 5.0 7.5 10.0
        y        (index) float64 4.8 7.2 12.0 7.2 2.4
      * index    (index) int64 0 1 2 3 4
    

    【讨论】:

    • 嗯 - 这似乎受到浮点问题的困扰。将索引乘以 10 然后将它们转换为整数可能会更幸运
    猜你喜欢
    • 1970-01-01
    • 2021-12-12
    • 2019-01-31
    • 2017-09-25
    • 1970-01-01
    • 2020-10-15
    • 2020-07-06
    • 1970-01-01
    • 2020-01-14
    相关资源
    最近更新 更多