如何在不重新采样的情况下将这个月度 xarray 数据集转换为年度平均值?
How turn this monthly xarray dataset into an annual mean without resampling?
我使用 open_dataset
和 decode_times=False
从服务器读取月平均表面温度的 xarray,因为 xarray 不理解日历类型。
经过一些操作后,我得到了表面温度 ('ts') 和时间 ('T') 的数据集 my_dataset
:
<xarray.Dataset>
Dimensions: (T: 1800)
Coordinates:
* T (T) float32 0.5 1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5 9.5 10.5 11.5 ...
Data variables:
ts (T) float64 246.6 247.9 250.7 260.1 271.9 281.1 283.3 280.5 ...
'T' 具有以下属性:
Attributes:
pointwidth: 1.0
calendar: 360
gridtype: 0
units: months since 0300-01-01
我想获取这个月度数据并计算年平均值,但是因为 T 坐标不是日期时间,所以我无法使用 xarray.Dataset.resample
。现在,我只是转换为一个 numpy 数组,但我想要一种方法来保留 xarray 数据集。
我目前的基本方式:
temps = np.mean(np.array(my_dataset['ts']).reshape(-1,12),axis=1)
years = np.array(my_dataset['T'])/12
感谢任何帮助,即使最好的方法是重新定义时间坐标以使用重采样。
编辑:
询问 xarray 是如何创建的,它是通过以下方式完成的:
import numpy as np
import matplotlib.pyplot as plt
import xarray as xr
filename = 'http://strega.ldeo.columbia.edu:81/CMIP5/.byScenario/.abrupt4xCO2/.atmos/.mon/.ts/ACCESS1-0/r1i1p1/.ts/dods'
ds = xr.open_dataset(filename,decode_times=False)
zonal_mean = ds.mean(dim='lon')
arctic_only = zonal.where(zonal['lat'] >= 60).dropna('lat')
weights = np.cos(np.deg2rad(arctic['lat']))/np.sum(np.cos(np.deg2rad(arctic['lat'])))
my_dataset = (arctic_only * weights).sum(dim='lat')
这是一个非常普遍的问题,尤其是对于来自 INGRID 的数据集。 xarray 无法解码单位为 "months since..." 的日期的原因是底层 netcdf4-python 库拒绝解析此类日期。这在 netcdf4-python github issue
中讨论
The problem with time units such as "months" is that they are not well defined. In contrast to days, hours, etc. the length of a month depends on the calendar used and even varies between different months.
不幸的是,INGRID 拒绝接受这一事实,并继续使用 "months" 作为其默认单位,尽管存在歧义。所以现在 INGRID 和 xarray / python-netcdf4.
之间存在令人沮丧的不兼容性
无论如何,这里有一个 hack 可以在不离开 xarray 的情况下完成你想要的东西
# create new coordinates for month and year
ds.coords['month'] = np.ceil(ds['T'] % 12).astype('int')
ds.coords['year'] = (ds['T'] // 12).astype('int')
# calculate monthly climatology
ds_clim = ds.groupby('month').mean(dim='T')
# calculate annual mean
ds_am = ds.groupby('year').mean(dim='T')
我使用 open_dataset
和 decode_times=False
从服务器读取月平均表面温度的 xarray,因为 xarray 不理解日历类型。
经过一些操作后,我得到了表面温度 ('ts') 和时间 ('T') 的数据集 my_dataset
:
<xarray.Dataset>
Dimensions: (T: 1800)
Coordinates:
* T (T) float32 0.5 1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5 9.5 10.5 11.5 ...
Data variables:
ts (T) float64 246.6 247.9 250.7 260.1 271.9 281.1 283.3 280.5 ...
'T' 具有以下属性:
Attributes:
pointwidth: 1.0
calendar: 360
gridtype: 0
units: months since 0300-01-01
我想获取这个月度数据并计算年平均值,但是因为 T 坐标不是日期时间,所以我无法使用 xarray.Dataset.resample
。现在,我只是转换为一个 numpy 数组,但我想要一种方法来保留 xarray 数据集。
我目前的基本方式:
temps = np.mean(np.array(my_dataset['ts']).reshape(-1,12),axis=1)
years = np.array(my_dataset['T'])/12
感谢任何帮助,即使最好的方法是重新定义时间坐标以使用重采样。
编辑: 询问 xarray 是如何创建的,它是通过以下方式完成的:
import numpy as np
import matplotlib.pyplot as plt
import xarray as xr
filename = 'http://strega.ldeo.columbia.edu:81/CMIP5/.byScenario/.abrupt4xCO2/.atmos/.mon/.ts/ACCESS1-0/r1i1p1/.ts/dods'
ds = xr.open_dataset(filename,decode_times=False)
zonal_mean = ds.mean(dim='lon')
arctic_only = zonal.where(zonal['lat'] >= 60).dropna('lat')
weights = np.cos(np.deg2rad(arctic['lat']))/np.sum(np.cos(np.deg2rad(arctic['lat'])))
my_dataset = (arctic_only * weights).sum(dim='lat')
这是一个非常普遍的问题,尤其是对于来自 INGRID 的数据集。 xarray 无法解码单位为 "months since..." 的日期的原因是底层 netcdf4-python 库拒绝解析此类日期。这在 netcdf4-python github issue
中讨论不幸的是,The problem with time units such as "months" is that they are not well defined. In contrast to days, hours, etc. the length of a month depends on the calendar used and even varies between different months.
INGRID 拒绝接受这一事实,并继续使用 "months" 作为其默认单位,尽管存在歧义。所以现在 INGRID 和 xarray / python-netcdf4.
之间存在令人沮丧的不兼容性无论如何,这里有一个 hack 可以在不离开 xarray 的情况下完成你想要的东西
# create new coordinates for month and year
ds.coords['month'] = np.ceil(ds['T'] % 12).astype('int')
ds.coords['year'] = (ds['T'] // 12).astype('int')
# calculate monthly climatology
ds_clim = ds.groupby('month').mean(dim='T')
# calculate annual mean
ds_am = ds.groupby('year').mean(dim='T')