LCT*_*LCT 6 python dask python-xarray
我有一个 4D xarray 数据集。我想在特定维度(这里是时间)上的两个变量之间进行线性回归,并将回归参数保留在 3D 数组中(其余维度)。我设法通过使用此串行代码获得了我想要的结果,但速度相当慢:
# add empty arrays to store results of the regression
res_shape = tuple(v for k,v in ds[x].sizes.items() if k != 'year')
res_dims = tuple(k for k,v in ds[x].sizes.items() if k != 'year')
ds[sl] = (res_dims, np.empty(res_shape, dtype='float32'))
ds[inter] = (res_dims, np.empty(res_shape, dtype='float32'))
# Iterate in kept dimensions
for lat in ds.coords['latitude']:
for lon in ds.coords['longitude']:
for duration in ds.coords['duration']:
locator = {'longitude':lon, 'latitude':lat, 'duration':duration}
sel = ds.loc[locator]
res = scipy.stats.linregress(sel[x], sel[y])
ds[sl].loc[locator] = res.slope
ds[inter].loc[locator] = res.intercept
Run Code Online (Sandbox Code Playgroud)
我怎样才能加速和并行化这个操作?
我知道这apply_ufunc可能是一个选项(并且可以与 dask 并行化),但我没有设法使参数正确。
以下问题是相关的,但没有答案:
编辑 2:将上一个编辑移至答案
LCT之前的回答涵盖了这里应该说的大部分内容,但是我认为可以将dask='parallelized'多个输出结合起来,就像您从scipy.stats.linregress.
这里的技巧是将多个输出堆叠到一个数组中,然后输出该数组,您还必须使用 kwargoutput_core_dims来指定调用的 DataArray 输出apply_ufunc()现在将具有额外的维度:
def new_linregress(x, y):
# Wrapper around scipy linregress to use in apply_ufunc
slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
return np.array([slope, intercept, r_value, p_value, std_err])
Run Code Online (Sandbox Code Playgroud)
# return a new DataArray
stats = xr.apply_ufunc(new_linregress, ds[x], ds[y],
input_core_dims=[['year'], ['year']],
output_core_dims=[["parameter"]],
vectorize=True,
dask="parallelized",
output_dtypes=['float64'],
output_sizes={"parameter": 5},
)
Run Code Online (Sandbox Code Playgroud)
注意此方法目前仅适用于dask='parallelized'您有的情况dask<2.0,但如果您有其他类似的东西,它似乎适用于多个输出dask='allowed'。查看此Github 问题了解更多详细信息。
希望能帮助到你!
编辑:我已获悉该dask<2.0问题已得到纠正,只要您有xarray>=0.15.0!所以可以使用dask='parallelized'now 来加快速度。:)
可以通过像这样传递来应用scipy.stats.linregress(和其他非 ufunc)到 xarray 数据集:apply_ufunc()vectorize=True
# return a tuple of DataArrays
res = xr.apply_ufunc(scipy.stats.linregress, ds[x], ds[y],
input_core_dims=[['year'], ['year']],
output_core_dims=[[], [], [], [], []],
vectorize=True)
# add the data to the existing dataset
for arr_name, arr in zip(array_names, res):
ds[arr_name] = arr
Run Code Online (Sandbox Code Playgroud)
虽然还是连续剧 apply_ufunc但在这种特定情况下比循环实现快 36 倍左右。
然而,与 dask 的并行化仍然没有像来自 的多个输出那样实现scipy.stats.linregress:
NotImplementedError:dask='parallelized' 尚不支持来自 apply_ufunc 的多个输出
| 归档时间: |
|
| 查看次数: |
786 次 |
| 最近记录: |