尝试在 xarray 上应用 fftconvolve

Trying to apply fftconvolve over xarray

我有一个 3D xarray DataArray 和一个 1D xarray DataArray。 3D 数组的一维与另一维的一维大小相同。我想沿着这些相应的维度应用 scipy.signal.fftconvolve。但是我得到一个错误。这是一些最小的示例代码:

import numpy as np
from scipy.signal import fftconvolve
import xarray as xr

xarr1 = xr.DataArray(np.random.random([10,20,500]), 
                     dims=('dim1', 'dim2', 'sample'))
xarr2 = xr.DataArray(np.random.random(500), 
                     dims=('sample',))
res = xr.apply_ufunc(fftconvolve, xarr1, xarr2, 
                     input_core_dims=[['sample'], ['sample']], 
                     kwargs={'mode': 'same'}, 
                     vectorize=True)

我想做的相当于这个:

res = np.zeros(xarr1.shape)
for i1 in range(xarr1.shape[0]):
    for i2 in range(xarr1.shape[1]):
       res[i1, i2, :] = fftconvolve(xarr1[i1, i2, :], xarr2, mode='same')

但是 apply_ufunc 版本出现以下错误:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-174-4f45f68ab252> in <module>()
    7 xarr2 = xr.DataArray(np.random.random(500), 
    8                      dims=('sample',))
----> 9 res = xr.apply_ufunc(fftconvolve, xarr1, xarr2, input_core_dims=[['sample'], ['sample']], kwargs={'mode': 'same'}, vectorize=True)

~\Anaconda3\envs\dataproc\lib\site-packages\xarray\core\computation.py in apply_ufunc(func, *args, **kwargs)
    932                                      join=join,
    933                                      exclude_dims=exclude_dims,
--> 934                                      keep_attrs=keep_attrs)
    935     elif any(isinstance(a, Variable) for a in args):
    936         return variables_ufunc(*args)

~\Anaconda3\envs\dataproc\lib\site-packages\xarray\core\computation.py in apply_dataarray_ufunc(func, *args, **kwargs)
    209 
    210     data_vars = [getattr(a, 'variable', a) for a in args]
--> 211     result_var = func(*data_vars)
    212 
    213     if signature.num_outputs > 1:

~\Anaconda3\envs\dataproc\lib\site-packages\xarray\core\computation.py in apply_variable_ufunc(func, *args, **kwargs)
    563             raise ValueError('unknown setting for dask array handling in '
    564                              'apply_ufunc: {}'.format(dask))
--> 565     result_data = func(*input_data)
    566 
    567     if signature.num_outputs > 1:

~\Anaconda3\envs\dataproc\lib\site-packages\numpy\lib\function_base.py in __call__(self, *args, **kwargs)
2737             vargs.extend([kwargs[_n] for _n in names])
2738 
-> 2739         return self._vectorize_call(func=func, args=vargs)
2740 
2741     def _get_ufunc_and_otypes(self, func, args):

~\Anaconda3\envs\dataproc\lib\site-packages\numpy\lib\function_base.py in _vectorize_call(self, func, args)
2803         """Vectorized call to `func` over positional `args`."""
2804         if self.signature is not None:
-> 2805             res = self._vectorize_call_with_signature(func, args)
2806         elif not args:
2807             res = func()

~\Anaconda3\envs\dataproc\lib\site-packages\numpy\lib\function_base.py in _vectorize_call_with_signature(self, func, args)
2867 
2868             for output, result in zip(outputs, results):
-> 2869                 output[index] = result
2870 
2871         if outputs is None:

ValueError: setting an array element with a sequence.

指定 output_core_dims 解决了这个问题,

res = xr.apply_ufunc(fftconvolve, xarr1, xarr2, 
                     input_core_dims=[['sample'], ['sample']], 
                     output_core_dims=[['sample']],
                     kwargs={'mode': 'same'}, vectorize=True)