我有一个netCDF文件,其时间维度包含2小时的数据。我想平均每个月的每小时平均得分。我试过这个:
import xarray as xr
ds = xr.open_mfdataset('ecmwf_usa_2015.nc')
ds.groupby(['time.month', 'time.hour']).mean('time')
但是我收到了这个错误:
*** TypeError: `group` must be an xarray.DataArray or the name of an xarray variable or dimension
我该如何解决这个问题?如果我这样做:
ds.groupby('time.month', 'time.hour').mean('time')
我没有收到错误,但结果的时间维度为12(每个月一个值),而我想要每个月的平均小时数,即每12个月24个值。数据可在此处获取:https://www.dropbox.com/s/yqgg80wn8bjdksy/ecmwf_usa_2015.nc?dl=0
答案 0 :(得分:5)
您正在获取 TypeError:group
必须是xarray.DataArray或xarray变量或维度的名称,因为ds.groupby()应该采用xarray数据集变量或数组,你传递了一系列变量。
按文档group by documentation推荐分组,并将数据集转换为splits
或bins
,然后应用groupby('time.hour')
这是因为在一个月或一个小时后逐个或一起应用groupby会聚合所有数据。如果您将它们拆分为月份数据,则可以按每月的平均值进行分组。
您可以尝试使用文档中提到的方法:
GroupBy:split-apply-combine
xarray支持使用与pandas相同的API进行“分组依据”操作 实施split-apply-combine策略:
- 将您的数据拆分为多个独立的组。 => 使用
将它们拆分数月groupby_bins
- 将一些功能应用于每个组。 => 按
分组- 将您的组合并回一个数据对象。 **应用汇总函数
mean('time')
警告 :并非所有netcdfs都可以转换为panda数据帧,转换时可能会丢失元数据。
通过df = ds.to_dataframe()
将ds转换为pandas数据帧并使用
根据需要使用pandas.Grouper
df.set_index('time').groupby([pd.Grouper(freq='1M'), 't2m']).mean()
注意:我在pandas.TimeGrouper
看到了几个答案,但已弃用,现在必须使用pandas.Grouper
。
由于您的数据集太大且问题没有最小化数据并且正在消耗大量资源,我建议您在pandas上查看这些示例
答案 1 :(得分:1)
万一您还没有解决问题,可以按照以下方式进行:
# define a function with the hourly calculation:
def hour_mean(x):
return x.groupby('time.hour').mean('time')
# group by month, then apply the function:
ds.groupby('time.month').apply(hour_mean)
这与@Prateek提供的第一个选项中的策略相同,并且基于文档,但是我对文档的了解并不明确,因此希望对此有所帮助。您无法将groupby操作应用于groupby对象,因此必须将其构建为函数并使用.apply()使其起作用。
答案 2 :(得分:1)
使用xarray库在netcdf文件上检索多时间groupby函数问题的另一种解决方案是使用称为“ resample”的xarray-DataArray方法和“ groupby”方法。这种方法也可用于xarray-DataSet对象。
通过这种方法,人们可以检索诸如每月每小时平均值或其他类型的时间汇总(即:每月每月平均值,半年两次的三个月总和等)之类的值。
下面的示例使用标准xarray的每日气温(Tair)教程数据集。注意,我必须将教程数据的时间维度转换为pandas datetime对象。如果未应用此转换,则重采样功能将失败,并会显示一条错误消息(见下文):
错误消息:
“ TypeError:仅对DatetimeIndex,TimedeltaIndex或PeriodIndex有效,但有一个'Index'实例”
尽管存在时间索引问题(这可能是StackOverFlow中讨论的另一个问题),但是下面的代码提供了xarray对象中多时间分组问题的两种可能的解决方案。第一个使用xarray.core.groupby.DataArrayGroupBy类,而第二个仅使用普通xarray-dataArray和xarray-DataSet类中的groupby方法。
真诚的,
Philipe Riskalla Leal
代码段:
ds = xr.tutorial.open_dataset('rasm').load()
def parse_datetime(time):
return pd.to_datetime([str(x) for x in time])
ds.coords['time'] = parse_datetime(ds.coords['time'].values)
# 1° Option for multitemporal aggregation:
time_grouper = pd.Grouper(freq='Y')
grouped = xr.core.groupby.DataArrayGroupBy(ds, 'time', grouper=time_grouper)
for idx, sub_da in grouped:
print(sub_da.resample({'time':'3M'}).mean().coords)
# 2° Option for multitemporal aggregation:
grouped = ds.groupby('time.year')
for idx, sub_da in grouped:
print(sub_da.resample({'time':'3M'}).mean().coords)
答案 3 :(得分:0)
不是python解决方案,但我认为这是你在bash脚本循环中使用CDO的方法:
# loop over months:
for i in {1..12}; do
# This gives the hourly mean for each month separately
cdo yhourmean -selmon,${i} datafile.nc mon${i}.nc
done
# merge the files
cdo mergetime mon*.nc hourlyfile.nc
rm -f mon*.nc # clean up the files
请注意,如果您的数据未在1月开始,那么您将在最终文件时间内获得“跳转”...我认为可以通过设置yhourmean命令之后的年份进行排序,如果这是一个问题你。
答案 4 :(得分:0)
这是什么
import xarray as xr
ds = xr.open_mfdataset('ecmwf_usa_2015.nc')
print ds.groupby('time.hour' ).mean('time')
我得到这样的事情:
尺寸:(小时:24,纬度:93,经度: 281)坐标:
- 经度(经度)float32 230.0 230.25 230.5 230.75 231.0 231.25 ... *纬度(纬度)float32 48.0 47.75 47.5 47.25 47.0 46.75 46.5 ... *小时(小时)int64 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ...
我认为这就是你想要的。