如何将带有complex128数据的xarray.DataArray保存到netcdf

时间:2017-11-07 16:33:42

标签: python netcdf4 xarray

我在xarray数据集中有一些复杂数据(numpy dtype complex128),我想用to_netcdf保存。我收到以下错误:

TypeError: illegal primitive data type, must be one of dict_keys(['S1', 'i1', 'u1', 'i2', 'u2', 'i4', 'u4', 'i8', 'u8', 'f4', 'f8']), got complex128

我知道我将数据类型传递给不支持的底层netCDF4。我还在netcdf4的复合数据类型上找到了https://unidata.github.io/netcdf4-python/。但不幸的是,我不知道如何将其应用于我的问题,因为我没有直接使用netcdf4库。

我可以在保留数据类型的同时将数据类型complex128的数据保存到netcdf(使用xarray.DataArray.to_netcdf)吗?

MWE:

import numpy as np
import xarray as xr
complex = [np.complex(1.0, 1.0), np.complex(2.0, 1.0), np.complex(3.0, 1.0), np.complex(4.0, 1.0)]
data = xr.DataArray(complex)
data.to_netcdf(r'test.nc')

2 个答案:

答案 0 :(得分:2)

NetCDF作为文件格式不支持复杂数据。显然,地球科学用户并不十分需要保存复杂的价值观。

也就是说,您确实可以使用某种特殊约定将complex128数据写入netCDF文件,例如使用自定义复合数据类型。这类似于h5py使用的方法。这确实需要在xarray中实现:欢迎拉取请求。

使用当前版本的xarray,您有两个序列化复杂值的选项:

  1. 使用engine='h5netcdf'。这使用h5py的约定来编写复杂数据。不幸的是,这会导致无效的netCDF文件unreadable by netCDF-C。 如果您尝试,您应该会看到一条警告消息。在xarray的未来版本中,我们可能需要使用to_hdf5()而不是to_netcdf()等专用方法来创建此类无效文件。

  2. 将数据转换为实部和虚部,并将它们保存为单独的变量。从磁盘读取数据时,将它们组合回复杂值。选择最适合您的特殊约定。

  3. 如,

    def save_complex(data_array, *args, **kwargs):
        ds = xarray.Dataset({'real': data_array.real, 'imag': data_array.imag})
        return ds.to_netcdf(*args, **kwargs)
    
    def read_complex(*args, **kwargs):
        ds = xarray.open_dataset(*args, **kwargs)
        return ds['real'] + ds['imag'] * 1j
    

答案 1 :(得分:1)

除了shoyer提供的两个非常好的选择之外,还有另一种在实践中有用的解决方案:

向数据集添加另一个长度为2的维度,该维度表示数据的实部和虚部。这类似于将实部和虚部存储在单独的变量中,但是根据我的经验,在某些情况下使用它会更好。

例如,存储一个维度为float的{​​{1}}变量,其中(x, ReIm)是实数,而ReIm是一个任意维度,给出了一个内存布局等效于C语言中沿float _Complex的维度x的1d数组,或者等效于C ++中沿x的维度。

阅读和写作是这样的:

std::complex<float>

如示例所示,此方法很容易用于数据集(而不仅仅是数据数组)。