xarray 在按元素和两个大小相等的数组时给出错误的结果形状
xarray gives wrong shape of result when taking elementwise and of two arrays of equal size
我有一个使用 xarray
从 NetCDF 文件加载的二维数组,我想通过将单元格值与相邻单元格值进行比较来进行某种边缘检测。我想出了这个代码:
import numpy as np
import xarray as xr
d = xr.open_dataset('https://thredds.met.no/thredds/dodsC/barents25km_files/Barents-2.5km_ZDEPTHS_his.an.2021112900.nc')
# Compare values to neighbouring cells
threshold = 0.7
mask = (d.ice_concentration[0,1:-1,1:-1] < threshold) & (d.ice_concentration[0,1:-1,:-2] > threshold)
# Check shapes
print((d.ice_concentration[0,1:-1,1:-1] < threshold).shape)
print((d.ice_concentration[0,1:-1, :-2] > threshold).shape)
print(mask.shape)
输出:
(947, 737)
(947, 737)
(947, 736)
所以我的问题是我使用 &
在两个相同形状的数组上按元素取 and
,但结果具有不同的形状。我假设在幕后发生了一些与维度有关的神奇事情,这样每个单元格都会与自身进行比较,而不是与相邻的单元格进行比较。 np.sum(mask)
returns 零这一事实支持了这一点。
如果我在几个地方添加 .values
,我会得到正确的形状,并且会得到我期望的结果,其中 np.sum(mask)
是一个大于零的数字:
# Compare values to neighbouring cells
threshold = 0.7
mask = (d.ice_concentration[0,1:-1,1:-1].values < threshold) & (d.ice_concentration[0,1:-1,:-2].values > threshold)
# Check shapes
print((d.ice_concentration[0,1:-1,1:-1] < threshold).shape)
print((d.ice_concentration[0,1:-1, :-2] > threshold).shape)
print(mask.shape)
输出:
(947, 737)
(947, 737)
(947, 737)
这是xarray
的故意行为吗?我想如果我试图比较具有相同维度的不同数组,这种行为可能是有意义的,但在这种情况下,它的意义为零(至少对我而言)。还是我做错了什么?
xarray 在执行数据操作时使用沿给定维度的标签来对齐数据。通过这种方式,它在处理未对齐坐标方面更类似于 pandas 而不是 numpy,尽管默认情况下 xarray 始终使用内部连接对齐数据:
In [1]: import xarray as xr, pandas as pd, numpy as np
In [2]: da = xr.DataArray(np.arange(5), dims=['level'], coords=[list('abcde')])
In [3]: da
Out[3]:
<xarray.DataArray (level: 5)>
array([0, 1, 2, 3, 4])
Coordinates:
* level (level) <U1 'a' 'b' 'c' 'd' 'e'
查看示例中的两种情况时,您正在使用偏移量对数据进行切片(slice(0, length-1)
与 slice(1, length)
)。执行此操作时,请注意“级别”的索引不再对齐:
In [4]: a = da[:len(da.level)-1]
...: b = da[1:len(da.level)]
In [5]: a
Out[5]:
<xarray.DataArray (level: 4)>
array([0, 1, 2, 3])
Coordinates:
* level (level) <U1 'a' 'b' 'c' 'd'
In [6]: b
Out[6]:
<xarray.DataArray (level: 4)>
array([1, 2, 3, 4])
Coordinates:
* level (level) <U1 'b' 'c' 'd' 'e'
将两者相加时,或在涉及广播和自动对齐的任何操作中(请参阅下面的文档参考),将从结果中删除缺失值。此外,在结果中,请注意总和是元素总和,其中每个元素基于标签 (b + b, c + c, d + d) 对齐,而不是基于位置 (b + a, c + b , d + c).
In [7]: a + b
Out[7]:
<xarray.DataArray (level: 3)>
array([2, 4, 6])
Coordinates:
* level (level) <U1 'b' 'c' 'd'
你要找的是首先使用 shift
方法移动轴标签,以便坐标标签对齐 在你做加法之前 :
In [10]: c = da.shift(level=-1)
In [11]: c
Out[11]:
<xarray.DataArray (level: 5)>
array([ 1., 2., 3., 4., nan])
Coordinates:
* level (level) <U1 'a' 'b' 'c' 'd' 'e'
In [12]: a + c
Out[12]:
<xarray.DataArray (level: 4)>
array([1., 3., 5., 7.])
Coordinates:
* level (level) <U1 'a' 'b' 'c' 'd'
现在,当您在 a + c
上添加时,坐标会按您喜欢的方式排列。
有关详细信息,请参阅 broadcasting by dimension name and automatic alignment 上的 xarray 计算文档。
我有一个使用 xarray
从 NetCDF 文件加载的二维数组,我想通过将单元格值与相邻单元格值进行比较来进行某种边缘检测。我想出了这个代码:
import numpy as np
import xarray as xr
d = xr.open_dataset('https://thredds.met.no/thredds/dodsC/barents25km_files/Barents-2.5km_ZDEPTHS_his.an.2021112900.nc')
# Compare values to neighbouring cells
threshold = 0.7
mask = (d.ice_concentration[0,1:-1,1:-1] < threshold) & (d.ice_concentration[0,1:-1,:-2] > threshold)
# Check shapes
print((d.ice_concentration[0,1:-1,1:-1] < threshold).shape)
print((d.ice_concentration[0,1:-1, :-2] > threshold).shape)
print(mask.shape)
输出:
(947, 737)
(947, 737)
(947, 736)
所以我的问题是我使用 &
在两个相同形状的数组上按元素取 and
,但结果具有不同的形状。我假设在幕后发生了一些与维度有关的神奇事情,这样每个单元格都会与自身进行比较,而不是与相邻的单元格进行比较。 np.sum(mask)
returns 零这一事实支持了这一点。
如果我在几个地方添加 .values
,我会得到正确的形状,并且会得到我期望的结果,其中 np.sum(mask)
是一个大于零的数字:
# Compare values to neighbouring cells
threshold = 0.7
mask = (d.ice_concentration[0,1:-1,1:-1].values < threshold) & (d.ice_concentration[0,1:-1,:-2].values > threshold)
# Check shapes
print((d.ice_concentration[0,1:-1,1:-1] < threshold).shape)
print((d.ice_concentration[0,1:-1, :-2] > threshold).shape)
print(mask.shape)
输出:
(947, 737)
(947, 737)
(947, 737)
这是xarray
的故意行为吗?我想如果我试图比较具有相同维度的不同数组,这种行为可能是有意义的,但在这种情况下,它的意义为零(至少对我而言)。还是我做错了什么?
xarray 在执行数据操作时使用沿给定维度的标签来对齐数据。通过这种方式,它在处理未对齐坐标方面更类似于 pandas 而不是 numpy,尽管默认情况下 xarray 始终使用内部连接对齐数据:
In [1]: import xarray as xr, pandas as pd, numpy as np
In [2]: da = xr.DataArray(np.arange(5), dims=['level'], coords=[list('abcde')])
In [3]: da
Out[3]:
<xarray.DataArray (level: 5)>
array([0, 1, 2, 3, 4])
Coordinates:
* level (level) <U1 'a' 'b' 'c' 'd' 'e'
查看示例中的两种情况时,您正在使用偏移量对数据进行切片(slice(0, length-1)
与 slice(1, length)
)。执行此操作时,请注意“级别”的索引不再对齐:
In [4]: a = da[:len(da.level)-1]
...: b = da[1:len(da.level)]
In [5]: a
Out[5]:
<xarray.DataArray (level: 4)>
array([0, 1, 2, 3])
Coordinates:
* level (level) <U1 'a' 'b' 'c' 'd'
In [6]: b
Out[6]:
<xarray.DataArray (level: 4)>
array([1, 2, 3, 4])
Coordinates:
* level (level) <U1 'b' 'c' 'd' 'e'
将两者相加时,或在涉及广播和自动对齐的任何操作中(请参阅下面的文档参考),将从结果中删除缺失值。此外,在结果中,请注意总和是元素总和,其中每个元素基于标签 (b + b, c + c, d + d) 对齐,而不是基于位置 (b + a, c + b , d + c).
In [7]: a + b
Out[7]:
<xarray.DataArray (level: 3)>
array([2, 4, 6])
Coordinates:
* level (level) <U1 'b' 'c' 'd'
你要找的是首先使用 shift
方法移动轴标签,以便坐标标签对齐 在你做加法之前 :
In [10]: c = da.shift(level=-1)
In [11]: c
Out[11]:
<xarray.DataArray (level: 5)>
array([ 1., 2., 3., 4., nan])
Coordinates:
* level (level) <U1 'a' 'b' 'c' 'd' 'e'
In [12]: a + c
Out[12]:
<xarray.DataArray (level: 4)>
array([1., 3., 5., 7.])
Coordinates:
* level (level) <U1 'a' 'b' 'c' 'd'
现在,当您在 a + c
上添加时,坐标会按您喜欢的方式排列。
有关详细信息,请参阅 broadcasting by dimension name and automatic alignment 上的 xarray 计算文档。