10

我有一个 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

4

5 回答 5

6

你得到TypeError: groupmust be an x​​array.DataArray or the name of an x​​array variable or dimension因为 ds.groupby() 应该采用 xarray dataset variable or array ,你传递了一个变量列表。

你有两个选择:

1. xarray bins --> 按小时分组

逐个文档组按文档组引用并将数据集转换为splitsorbins然后应用groupby('time.hour')

这是因为按月应用 groupby,然后逐小时或一起应用 groupby 聚合所有数据。如果您将它们拆分为月份数据,您将按每个月的平均值应用分组。

您可以尝试文档中提到的这种方法:

GroupBy:拆分应用组合

xarray 支持“group by”操作,使用与 pandas 相同的 API 来实现 split-apply-combine 策略:

  • 将您的数据分成多个独立的组。=>使用按月拆分它们groupby_bins
  • 对每个组应用一些功能。=>应用分组依据
  • 将您的组重新组合成一个数据对象。**应用聚合函数mean('time')

2.将其转换为pandas数据框并使用group by

警告:并非所有 netcdfs 都可以转换为 panda 数据帧,转换时可能会丢失元数据。

将 ds 转换为 pandas 数据帧df = ds.to_dataframe()并根据需要使用 group by 使用pandas.Grouperlike

df.set_index('time').groupby([pd.Grouper(freq='1M'), 't2m']).mean()

注意:我看到了几个答案,pandas.TimeGrouper但它已被弃用,pandas.Grouper现在必须使用一个。

由于您的数据集太大,并且问题没有最小化数据并且正在消耗大量资源,我建议您查看这些关于 pandas 的示例

  1. 按工作日分组
  2. 按时间分组
  3. 分组日期范围取决于每一行
  4. 按月和年分组和计数行
于 2018-04-09T04:38:33.503 回答
5

如果您还没有解决问题,您可以这样做:

# 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() 使其工作。

于 2019-01-29T14:43:16.050 回答
1

使用 xarray 库在 netcdf 文件上检索多时间 groupby 函数的问题的另一个解决方案是使用称为“resample”的 xarray-DataArray 方法与“groupby”方法相结合。这种方法也适用于 xarray-DataSet 对象。

通过这种方法,人们可以检索诸如每月每小时平均值或其他类型的时间聚合(即:年度每月平均值、双年度三个月总和等)的值。

下面的示例使用每日气温 (Tair) 的标准 xarray 教程数据集。请注意,我必须将教程数据的时间维度转换为 pandas 日期时间对象。如果未应用此转换,重采样功能将失败,并出现错误消息(见下文):

错误信息:

“TypeError:仅对 DatetimeIndex、TimedeltaIndex 或 PeriodIndex 有效,但获得了 'Index' 的实例”

尽管存在时间索引问题(这可能是 StackOverFlow 中讨论的另一个问题),但下面的代码为 xarray 对象中的多时间分组问题提供了两种可能的解决方案。第一个使用 xarray.core.groupby.DataArrayGroupBy 类,而第二个只使用来自普通 xarray-dataArray 和 xarray-DataSet 类的 groupby 方法。

您忠诚的,

菲利普·里斯卡拉·里尔

代码片段:

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)
于 2019-10-31T17:36:20.617 回答
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 命令之后设置年份来进行排序。

于 2018-04-03T08:37:37.607 回答
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 1 7 13 13 14 15 16 17 18 ...

我认为这就是你想要的。

于 2018-04-07T19:32:49.733 回答