向xarray数据集添加“constant”维度。

7
我有一系列以CSV形式呈现的月度分格数据集。我想读取它们,添加一些维度,然后将其写入netcdf格式。过去我使用过xarray (xray) ,并且非常满意,所以我计划在这个任务中继续使用它。
我可以很容易地通过以下方式将它们转换成2D DataArray:
data = np.ones((360,720))
lats = np.arange(-89.75, 90, 0.5) * -1
lngs = np.arange(-179.75, 180, 0.5)
coords =  {'lat': lats, 'lng':lngs}
da = xr.DataArray(data, coords=coords)

但是,当我试图添加另一个维度来传达关于时间的信息(所有数据来自同一年/月)时,事情开始变得糟糕起来。
我尝试了两种方法来解决这个问题:
1)将我的输入数据扩展为m x n x 1,例如:
data = np.ones((360,720))
lats = np.arange(-89.75, 90, 0.5) * -1
lngs = np.arange(-179.75, 180, 0.5)
coords =  {'lat': lats, 'lng':lngs}
data = data[:,:,np.newaxis]

然后我按上述步骤进行操作,将coords更新为包含第三个维度的值。

lats = np.arange(-89.75, 90, 0.5) * -1
lngs = np.arange(-179.75, 180, 0.5)
coords =  {'lat': lats, 'lng':lngs}
coords['time'] = pd.datetime(year, month, day))
da = xr.DataArray(data, coords=coords)
da.to_dataset(name='variable_name')

这对于创建DataArray来说是可以的,但是当我试图转换为数据集(以便能够写入netCDF)时,会出现一个关于“ValueError:坐标对象必须是一维”的错误。
2)我尝试过的第二种方法是将我的DataArray转换为DataFrame,将索引设置为['lat','lng','time'],然后使用xr.Dataset.from_dataframe()返回到数据集。我已经尝试过这个方法,但是它需要20分钟以上才能完成,所以我中途就终止了进程。
有人知道如何获得具有月度“时间”维度的数据集吗?

谢谢您的提问。如果您能够发布完全可重现的示例,那么我们更容易进行交流。无论如何,我稍后会查看。 - Maximilian
@Maximilian 进行了一些编辑以支持复制/粘贴 -- 我在这里很少提问,所以如果您认为有任何进一步的编辑/样式更改可能会有帮助,我将不胜感激。 - badgley
1
Stephen 给出了理想的答案,所以我不会试图超越他。感谢您的编辑,现在好多了...如果您真的希望将来进行另一次改进,您的代码行可以放在块中(请注意 Stephan 在下面是如何做的)。 - Maximilian
2个回答

14
你的第一个例子很接近:
lats = np.arange(-89.75, 90, 0.5) * -1
lngs = np.arange(-179.75, 180, 0.5)
coords =  {'lat': lats, 'lng': lngs}
coords['time'] = [datetime.datetime(year, month, day)]
da = xr.DataArray(data, coords=coords, dims=['lat', 'lng', 'time'])
da.to_dataset(name='variable_name')

你会注意到我的版本有一些变化:
  1. 我传入了一个列表作为“time”坐标,而不是一个标量。如果你还要将“time”作为一个维度使用,你需要传入一个列表或一维数组,这样才能得到一个一维坐标变量。这就是错误信息“ValueError: Coordinate objects must be 1-dimensional”试图告诉你的(顺便说一句 - 如果你有关于如何使错误信息更有帮助的想法,我非常愿意听取!)。
  2. 我在DataArray构造函数中提供了一个“dims”参数。传入一个(无序)字典有一定的风险,因为迭代顺序不能保证。
  3. 我还切换到了“datetime.datetime”而不是“pd.datetime”。后者只是前者的别名。

另一个明智的方法是在将“time”作为标量坐标添加后,使用concat和一个项目的列表,例如:
lats = np.arange(-89.75, 90, 0.5) * -1
lngs = np.arange(-179.75, 180, 0.5)
coords =  {'lat': lats, 'lng': lngs, 'time': datetime.datetime(year, month, day)}
da = xr.DataArray(data, coords=coords, dims=['lat', 'lng'])
expanded_da = xr.concat([da], 'time')

这个版本很好地概括了从一系列天数中汇总数据的方法 - 你只需要让DataArrays的列表变得更长。根据我的经验,你之所以需要额外的维度,大多数情况下是为了能够沿着这个维度进行连接。长度为1的维度在其他方面并不是很有用。

我最终选择了第二种方法——这使我能够将我的纬度/经度数据保持为一个360x720的数组,并消除了我在原始问题公式中多余的步骤。 - badgley

4

您可以使用.expand_dims()添加一个新维度,使用.assign_coords()为相应的维度添加坐标值。以下代码将new_dim维度添加到ds数据集中,并使用您提供的list_of_values设置相应的坐标。

expanded_ds = ds.expand_dims("new_dim").assign_coords(new_dim=("new_dim", [list_of_values]))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接