Python 从netcdf文件中获取每个月的小时平均值

Python 从netcdf文件中获取每个月的小时平均值,python,netcdf,xarray,Python,Netcdf,Xarray,我有一个时间维度的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

我有一个时间维度的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个值。这里有数据:

不是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命令后的年份来排序。

这是什么

import xarray as xr
ds = xr.open_mfdataset('ecmwf_usa_2015.nc')
print ds.groupby('time.hour' ).mean('time')
我有这样的感觉:

尺寸:(小时:24,纬度:93,经度: 281)坐标:

  • 经度(经度)32 230.0 230.25 230.5 230.75 231.0 231.25 ... * 纬度(纬度)浮动32 48.0 47.75 47.5 47.25 47.0 46.75 46.5…*小时(小时)国际64 01 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

我想这就是你想要的。

你得到了类型错误:
必须是xarray.DataArray或xarray变量或维度的名称
,因为ds.groupby()应该接受xarray数据集变量或数组,所以你传递了一个变量列表

您有两个选择: 1.X阵列箱-->按小时分组 参考分组文档,将数据集转换为
拆分
存储箱
,然后应用
groupby('time.hour')

这是因为将groupby应用于每月,然后逐个应用小时,或者一起应用小时,是对所有数据的聚合。如果你将它们分割成月份数据,你将在每个月应用分组平均值

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

GroupBy:split-apply-combine

xarray支持“分组方式”操作,其API与pandas to相同 实施拆分应用联合收割机策略:

  • 将数据拆分为多个独立组。=>使用
    groupby\u bins将它们按月份分割
  • 对每个组应用一些函数。=>应用分组依据
  • 将您的组重新组合到单个数据对象中**应用聚合函数
    mean('time')
2.将其转换为pandas dataframe并使用group by 警告:并非所有NetCDF都可转换为熊猫数据帧,转换时可能会丢失元数据

通过
df=ds.to_dataframe()
将ds转换为熊猫数据帧并使用 使用
pandas.gropper
like按需要分组

df.set_index('time').groupby([pd.Grouper(freq='1M'), 't2m']).mean()
注意:我看到了关于
pandas.TimeGrouper
的两个答案,但它已被弃用,现在必须使用
pandas.Grouper

由于您的数据集太大,而且问题并没有最小化数据,并且在处理数据时会消耗大量资源,所以我建议您看看这些关于熊猫的示例


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

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

    使用xarray库通过netcdf文件检索多时groupby函数的另一个解决方案是使用称为“重采样”的xarray DataArray方法以及“groupby”方法。这种方法也适用于xarray数据集对象

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

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

    错误消息:

    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)
    

    我相信
    ds
    是一个而不是一个,对吗?请提供一些样本数据,并澄清在没有数据的情况下,小时会发生什么。如果应考虑缺失数据,则需要重新采样too@SiggyF,您是对的,ds是通过在netCDF中读取而生成的xarray.Datasetfile@MaartenFabr首先,我将尝试获取一个示例数据集(完整数据集的大小为seveal GBs)。您可以假设不存在缺失数据—使用虚拟(如随机)数据的最小示例通常效果最好。虽然重点关注熊猫,但这个问题/答案可能会有所帮助:谢谢@Adrian,我正在寻找python soln,但我很感激你的努力。我也这么认为。但这是24。OP需要24*12