python-xarray:如何创建Dataset并将迭代结果分配给Dataset?

0 投票
1 回答
23 浏览
提问于 2025-04-14 16:35

我有一个for循环,它在一些数据上进行分析并返回一些值。由于一些无聊的原因,这个循环不能轻易地用向量化的方式处理。我想创建一个数据集,然后在循环中逐步将结果赋值给这个数据集。

Dataset.update

如果我写一些代码,使用Dataset.update,像这样:

import numpy as np
from xarray import Dataset, cftime_range, concat

times = cftime_range(start="2024-01-01", end="2024-01-02", freq="H")

test_xarray = Dataset(coords={"time": None, "mlt": np.arange(24)})

for time in times:
    test_for_this_time = Dataset({"x": (["time", "mlt"], np.random.random((1, 24)))},
                                 coords={"time": np.array([time]), "mlt": np.arange(24)})
    test_xarray.update(test_for_this_time)

print(test_xarray)

我得到的结果是:

<xarray.Dataset>
Dimensions:  (time: 1, mlt: 24)
Coordinates:
  * time     (time) object 2024-01-01 00:00:00
  * mlt      (mlt) int64 0 1 2 3 4 5 6 7 8 9 ... 14 15 16 17 18 19 20 21 22 23
Data variables:
    x        (time, mlt) float64 nan nan nan nan nan nan ... nan nan nan nan nan

Dataset.merge

这显然不是我想要的,所以我尝试用Dataset.merge来代替update

import numpy as np
from xarray import Dataset, cftime_range, concat

times = cftime_range(start="2024-01-01", end="2024-01-02", freq="H")

test_xarray = Dataset(coords={"time": None, "mlt": np.arange(24)})

for time in times:
    test_for_this_time = Dataset({"x": (["time", "mlt"], np.random.random((1, 24)))},
                                 coords={"time": np.array([time]), "mlt": np.arange(24)})
    test_xarray = test_xarray.merge(test_for_this_time)

print(test_xarray)

我得到的结果是:

<xarray.Dataset>
Dimensions:  (time: 25, mlt: 24)
Coordinates:
  * time     (time) object 2024-01-01 00:00:00 ... 2024-01-02 00:00:00
  * mlt      (mlt) int64 0 1 2 3 4 5 6 7 8 9 ... 14 15 16 17 18 19 20 21 22 23
Data variables:
    x        (time, mlt) float64 0.6399 0.6227 0.7972 ... 0.7804 0.8763 0.7198

这确实达到了我的目的,所以太好了,但我不明白我在第一种方法中做错了什么,因为我本来以为它会有效。

这是最好的方法吗?

我很好奇我在这里是否以最佳方式使用了xarray。我查阅了Stack Overflow和文档,但没有找到这种工作流程的例子。我也尝试过xarray.concat,但似乎也不太符合我的需求;它在time维度中留下了第一个None值。可能上面的方法是最好的,但如果不是的话,我非常希望能得到更好的建议。

1 个回答

0

我认为使用 Dataset.updateDataset.merge 这两种方法并不是最好的选择。每次在循环中都创建一个新的 Dataset,仅仅是为了往已有的 Dataset 里添加新数据,这样做其实没必要。

在你的例子中,你在循环中要遍历的坐标在循环开始之前就已经知道了。所以,我的建议是先创建一个包含正确形状但还没有填充数据(或者用一些占位符值填充)的 Dataset,然后在循环中再把值填进去:

import numpy as np
from xarray import Dataset, cftime_range, concat

times = cftime_range(start="2024-01-01", end="2024-01-02", freq="H")
mlt = np.arange(24)

test_xarray = Dataset(
    {"x": (["time", "mlt"], np.empty((times.size, mlt.size)))},
    coords={"time": times, "mlt": mlt},
)

for i, time in enumerate(times):
    test_xarray.x[i] = np.random.random(mlt.size)

这样做对你的应用来说可行吗?

撰写回答