You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于多个xarray DataArray构建动态递归计算函数

问题说明

需要基于两个时间序列类型的xarray DataArray计算生成投影结果DataArray:输出结果中初始年份的取值直接来自给定的given_projection,超过指定年份后的投影值由两部分共同决定:一是计算变量da_forcalculation的对应取值,二是前序年份已给定或已计算完成的历史值,该计算逻辑类似Excel中逐行引用前序单元格的递归计算、Lumina Analytica中的Dynamic函数效果。

参考Excel示例

在维度更少的场景下,这类递归计算在Excel中可以非常简便地实现,示例逻辑为当年取值等于上一年取值加上“其他变量”的对应值。

Excel递归计算示例截图

示例数据
import xarray as xr
given_projection = xr.DataArray.from_dict({'dims': ('energia_vehiculo', 'escenarios', 'ano'), 'attrs': {}, 'data': [[[0, 52.24501200000003, 54.334812480000025, 56.48730697440003], [0, 62.24937600000011, 64.73935104000013, 67.30402533120008]], [[299.695, 302.81542434, 305.9407876536, 309.070039330008], [299.695, 302.26518432, 304.8182980128, 307.35263017958397]]], 'coords': {'escenarios': {'dims': ('escenarios',), 'attrs': {}, 'data': ['Tendencial', 'Aspiracional']}, 'ano': {'dims': ('ano',), 'attrs': {}, 'data': [2020, 2021, 2022, 2023]}, 'tipo_vehiculo': {'dims': (), 'attrs': {}, 'data': 'Buses'}, 'energia_vehiculo': {'dims': ('energia_vehiculo',), 'attrs': {}, 'data': ['BEV', 'Convencional']}}, 'name': 'Nuevos 2020-2028'})
da_forcalculation = xr.DataArray.from_dict({'dims': ('escenarios', 'energia_vehiculo', 'ano'), 'attrs': {}, 'data': [[[5449.0, 5505.734988, 5562.559775520001, 5619.4552605456, 5676.401541062016, 5733.37789069487, 5790.362733696614, 5847.33361926215, 5904.267195156828], [0.0, 52.24501200000003, 106.57982448000006, 163.06713145440008, 221.77129877798416, 282.75840594192977, 346.09628887292206, 411.8545837587772, 480.1047719245175]], [[5449.0, 5495.730624, 5542.15087296, 5588.229639628799, 5633.934696615167, 5679.232664025139, 5724.088976252862, 5768.467847904085, 5812.332238830856], [0.0, 62.24937600000011, 126.98872704000024, 194.29275237120032, 264.23814322483247, 336.90363261166146, 412.3700463166736, 490.7203551168416, 572.0397282504896]]], 'coords': {'tipo_vehiculo': {'dims': (), 'attrs': {}, 'data': 'Buses'}, 'ano': {'dims': ('ano',), 'attrs': {}, 'data': [2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028]}, 'energia_vehiculo': {'dims': ('energia_vehiculo',), 'attrs': {}, 'data': ['Convencional', 'BEV']}, 'escenarios': {'dims': ('escenarios',), 'attrs': {}, 'data': ['Tendencial', 'Aspiracional']}}, 'name': 'Parque'})
第一次实现尝试
ds=da_forcalculation*0

for t in range(2020,2028):
    if t<=2023:
        ds=ds.drop_sel(ano=t)
        ds=xr.concat([ds,given_projection.sel(ano=t)], "ano")
    else:
        ds=ds.sortby('ano')
        v=da_forcalculation.sel(ano=t)+ds.shift(ano=3).sel(ano=t)
        ds=ds.drop_sel(ano=t)
        ds=xr.concat([ds,v], "ano")
ds

该方案可以勉强得到正确结果,但实现逻辑繁琐,存在大量重复的切片删除、拼接、排序操作,希望能找到更简洁优雅的实现方式(熟悉Lumina Analytica的用户可参考其Dynamic函数的效果)。

更新:第二次实现尝试(运行报错)

参考@Michael Delgado的建议,尝试使用loc直接赋值的写法简化实现,代码如下:

da_final=da_forcalculation*0

for t in range(2020,2028):
    if t<=2023:
        da_final.loc[{"ano":t}]=given_projection.loc[{"ano":t}]
    else:
        da_final=da_final.sortby('ano')
        da_final.loc[{"ano":t}] = da_forcalculation.loc[{"ano":t}]+da_final.shift(ano=3).loc[{"ano":t}]

运行时触发报错IndexError: dimension coordinate 'energia_vehiculo' conflicts between indexed and indexing objects,推测是两个输入数组的维度坐标存在顺序冲突,可能需要调用xr.DataArray.reindex完成维度对齐,但未找到正确的实现方法。


内容的提问来源于stack exchange,提问作者Alejandro Bañados P.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 17:30:46