【问题标题】:create netcdf using xarray with time stamp beyond year 2263使用时间戳超过 2263 年的 xarray 创建 netcdf
【发布时间】:2018-10-02 05:54:03
【问题描述】:

有没有办法使用 xarray 创建时间维度超过 2263 年的 netCDF 文件?

以下是如何创建 netCDF 玩具数据集http://xarray.pydata.org/en/stable/time-series.html

但是,时间维度有一种 pandas 日期时间索引,并且这些索引不超过 2263,如下所示: https://github.com/pandas-dev/pandas/issues/13346

【问题讨论】:

  • "注意当解码/编码非标准日历的日期时间或 1678 年之前或 2262 年之后的日期时,xarray 使用 netcdftime 库。netcdftime 以前与 netcdf4-python 包一起打包,但现在单独分发。netcdftime 是 xarray 的可选依赖项。"
  • 感谢@SeverinPappadeux,即使在使用pip install cftime 安装netcdftime 后我也会收到错误
  • @user308827,你能把你用过的代码添加到问题本身吗?
  • 由于该页面将在今年接近顶部,因此将链接留给未来的读者:youtube.com/watch?v=dQw4w9WgXcQ

标签: python netcdf xarray


【解决方案1】:

将来,您也许可以通过使用cftime 对象创建日期轴来做到这一点,但就目前而言,outstanding issue in xarray 不允许您编写包含此类对象的 netCDF 文件。

但是,即使您可以保存此类对象,最简单和最简洁的方法仍然是手动将该轴定义为具有某些单位的整数数组。

import numpy as np
import xarray as xr

days = np.asarray(range(100*365))

ds = xr.Dataset(
    {'time': (['time'], days, {'units': 'days since 2200-01-01 0:0:0'})}
)

print(ds['time'][-1]

ds.to_netcdf('test.nc')
ds = xr.open_dataset('test.nc')
print(ds['time'][-1])

给出输出

<xarray.DataArray 'time' ()>
array(36499)
Coordinates:
    time     int64 36499
Attributes:
    units:    days since 2200-01-01 0:0:0

紧随其后

<xarray.DataArray 'time' ()>
array(datetime.datetime(2299, 12, 7, 0, 0), dtype=object)
Coordinates:
    time     object 2299-12-07

请注意,当您重新打开数据集时,xarray 会自动对其进行解码。

您使用的“单位”属性应遵循CF conventions 的时间坐标。您可以根据需要将“天”替换为“小时”、“分钟”或“秒”。

这确实需要您手动计算所需的整数,如果您的时间轴以年为单位,这主要是困难的(因为“年”不是定义的时间度量单位,它的长度会因闰年而异)。如果是这种情况,您可以使用以下内容:

import cftime

# replace this to use a different calendar
Datetime = cftime.DatetimeProlepticGregorian

# make your list of Datetime objects
time_list = []
month = day = 1
hour = minute = second = 0
for year in range(2200, 2300, 1):
    time_list.append(Datetime(year, month, day, hour, minute, second))

# this will convert them into a time axis, here in units of
# 'days since 2200-01-01 0:0:0'
seconds_in_day = 60*60*24
day_list = []
for dt in time_list:
    time_since_2200 = dt - Datetime(2200, month, day, hour, minute, second)
    day_list.append(int(time_since_2200.total_seconds() / seconds_in_day))

您可以使用不同的cftime 类(例如cftime.DatetimeJuliancftime.DatetimeNoLeap)来使用不同的日历。应修改此代码以提供正确的time_list 供您使用。您还可以在其他时间单位中将seconds_in_day 切换为秒(并将该单位提供给xr.Dataset 调用)。

【讨论】:

    【解决方案2】:

    问题可能是 xarray 可以选择在 datetime.datetime 范围之外使用 netcdftime,但 pandas 没有。所以,即使安装了 netcdftime,像这个例子这样的东西也不起作用

    import numpy as np
    import pandas as pd
    import xarray as xr
    data = np.random.rand(4, 3)
    locs = ['IA', 'IL', 'IN']
    times = pd.date_range('2318-04-25', periods=4)
    da = xr.DataArray(data, coords=[times, locs], dims=['time', 'space'])
    

    当您尝试创建 pandas date_range 时,这将失败。即使提供 netcdftime.datetime 作为 pd.date_range() 的第一个参数也不起作用,因为 pandas 想要转换为它自己的有限日期时间类型。

    相反,您需要将时间直接指定给 xarray。不幸的是,这是我对 netcdf 的了解失败的地方,但我可以给你大纲,也许你可以从这里得到它。

    有多种方法可以在 DataArray 参数中指定日期。您需要以 netcdftime.datetime 类型为基础创建自己的日期范围。您可以使用 netcdftime.date2index() 创建日期索引,并使用它代替上面示例中的 pandas DateIndex。

    您可能应该发布显示问题的示例代码。我假设您正在尝试创建一个 DataArray,但也许这不是您遇到的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-19
      • 1970-01-01
      • 1970-01-01
      • 2018-12-31
      • 2021-03-06
      • 1970-01-01
      • 2019-08-02
      • 2021-03-28
      相关资源
      最近更新 更多