DataArray在简单计算中删除属性

Ban*_*Joe 1 python-xarray

我注意到,如果您有一个 xArray DatarArray 并对其执行简单(!)计算,则属性将被“删除”。

例子:

example            = xr.DataArray(np.array([1,2,3]), attrs={'one':1})
without_Attributes = example*3
Run Code Online (Sandbox Code Playgroud)

另一方面,如果您使用 numpy 特定函数(例如 .round(x), ..),则属性将保留。对此有合理的解释吗?有没有一种方法可以在不丢失其属性的情况下乘以 DataArray?

Mic*_*ado 6

来自 xarray 文档“您处理元数据的方法是什么?” :

我们坚信标记数据的力量!除了维度和坐标之外,xarray 还支持全局 ( Dataset) 和变量特定 ( DataArray) 属性 ( attrs) 形式的任意元数据。

标签的自动解释功能很强大,但也降低了灵活性。使用 xarray,我们在库理解的标签 (dimscoords) 与用户和用户代码的标签 ( attrs) 之间划定了一条明确的界限。例如,我们不会自动解释和强制执行单位或CF 约定。(一个例外是与 netCDF 文件之间的序列化。)

这种选择的含义是,除非明确标记,否则我们不会attrs通过大多数操作进行传播(某些方法有一个keep_attrs选项,并且有一个全局标记用于将其设置为始终 True 或 False)。同样,xarray 在组合数组和数据集时不会检查冲突attrs,除非使用选项明确请求compat='identical'。指导原则是不应让元数据成为障碍。

您可以使用以下命令在 xarray 中设置全局选项xr.set_options

In [14]: xr.set_options(keep_attrs=True)
Out[14]: <xarray.core.options.set_options at 0x133ef58e0>
Run Code Online (Sandbox Code Playgroud)

现在,属性被保留

In [15]: example * 3
Out[15]:
<xarray.DataArray (dim_0: 3)>
array([3, 6, 9])
Dimensions without coordinates: dim_0
Attributes:
    one:      1
Run Code Online (Sandbox Code Playgroud)

请注意,xarray 不会对这些属性执行任何“智能”操作,这就是为什么默认行为是在计算中删除它们。例如,一个带有单位的简单示例展示了设置如何keep_attrs=True偏离轨道:

In [17]: dist = xr.DataArray(np.array([1,2,3]), attrs={'units': 'm'})
    ...: dist
Out[17]:
<xarray.DataArray (dim_0: 3)>
array([1, 2, 3])
Dimensions without coordinates: dim_0
Attributes:
    units:    m

In [18]: rate = xr.DataArray(np.array([2, 2, 2]), attrs={'units': 'm/s'})
    ...: rate
Out[18]:
<xarray.DataArray (dim_0: 3)>
array([2, 2, 2])
Dimensions without coordinates: dim_0
Attributes:
    units:    m/s

In [19]: dist / rate
Out[19]:
<xarray.DataArray (dim_0: 3)>
array([0.5, 1. , 1.5])
Dimensions without coordinates: dim_0
Attributes:
    units:    m
Run Code Online (Sandbox Code Playgroud)

如果您想使用 xarray 显式处理计算中的单元,请查看pint-xarray ,它是将pint 项目的显式单元处理与 xarray集成的努力。这个项目是实验性的,API 并不稳定,但 pint-xarray 工作人员和 xarray 的核心团队最近都做了相当多的工作,朝着同一方向前进,所以我不认为这种协调会消失。

解决方法(或者可能是世界上最好的方法?)

请注意,由于DatasetDataArray属性只是字典,因此保存它们很容易:

In [17]: dist = xr.DataArray(np.array([1,2,3]), attrs={'units': 'm'})
    ...: dist
Out[17]:
<xarray.DataArray (dim_0: 3)>
array([1, 2, 3])
Dimensions without coordinates: dim_0
Attributes:
    units:    m

In [18]: rate = xr.DataArray(np.array([2, 2, 2]), attrs={'units': 'm/s'})
    ...: rate
Out[18]:
<xarray.DataArray (dim_0: 3)>
array([2, 2, 2])
Dimensions without coordinates: dim_0
Attributes:
    units:    m/s

In [19]: dist / rate
Out[19]:
<xarray.DataArray (dim_0: 3)>
array([0.5, 1. , 1.5])
Dimensions without coordinates: dim_0
Attributes:
    units:    m
Run Code Online (Sandbox Code Playgroud)

您甚至可以独立于 DataArray 或 Dataset 来使用它们:

In [22]: result = example * 3
    ...: result.attrs.update(example.attrs)

In [23]: result
Out[23]:
<xarray.DataArray (dim_0: 3)>
array([3, 6, 9])
Dimensions without coordinates: dim_0
Attributes:
    one:      1
Run Code Online (Sandbox Code Playgroud)

所以我通常采取的方法是在计算结束时显式复制我想要的属性。而且,如果需要,您可以使用 xarray-pint 显式处理单位,然后将其他元数据作为字典进行传递。