计算较长时间段内几个月的平均值

问题描述

我有几十年的 netCDF 月度温度数据,我想计算一年中每个月的所有年份的 6 个月平均值。例如,要获得 5 月的 6 个月平均值,我必须对每年(12 月、1 月、2 月、3 月、4 月)前的所有 5 个月和 5 月求和,然后计算平均值。我尝试应用 this guide,但使用的是六个月平均值而不是季节性平均值。

import pandas as pd
import xarray as xr
import numpy as np

ds = xr.open_dataset("...\\data.nc")

# Make a DataArray with the number of days in each month,size = len(time)
month_length = ds.time.dt.days_in_month

# Calculate the weights by grouping by 6 months
weights = xr.core.groupby.DataArrayGroupBy(month_length,'time',grouper=pd.Grouper(freq='6MS')) / xr.core.groupby.DataArrayGroupBy(month_length,grouper=pd.Grouper(freq='6MS')).sum()
print(weights)

# Test that the sum of the weights for each season is 1.0
np.testing.assert_allclose(xr.core.groupby.DataArrayGroupBy(weights,grouper=pd.Grouper(freq='6MS')).sum().values,np.ones(2))

# Calculate the weighted average
ds_weighted = xr.core.groupby.DataArrayGroupBy((ds * weights),grouper=pd.Grouper(freq='6MS')).sum(dim='time')

ds.to_netcdf(path="..\\output.nc")

但由于某种原因,权重加起来似乎不等于 1。
编辑:我现在决定尝试另一种解决体重问题的方法。首先,我决定将数据乘以月份中的天数:

month_length = ds.time.dt.days_in_month
ds_multbymonth = ds * month_length

然后我计算了 6 个月的滚动总和。

ds_rolledSum = ds_multbymonth.rolling(time=6,min_periods=6).sum().stack().reset_index('time')

最后,我想按月对汇总的变量进行分组,然后将它们除以每 6 个月总和的天数:

sumSixMonths = ds_rolledSum.groupby('time.month').sum()

这是一个相当不雅的解决方案,也许这里有人有更好的建议。

解决方法

如果你在 Linux/OSX 上工作,你可以使用我的包 nctoolkit (https://nctoolkit.readthedocs.io/en/latest/index.html)。

你说你的数据是每月的。所以你想要做的是计算一个窗口为 6 的滚动平均值。虽然滚动平均值通常是使用前后时间计算的。所以在下面的代码中,我使用了滚动总和然后除以 6。这将计算 6 个月的平均值,选择 5 月份,然后根据需要转换为 xarray。

import nctoolkit as nc
ds = nc.open_data("...\\data.nc")
ds.rolling_sum(window = 6)
ds.divde(6)
ds.select(month=5)
ds_xr = ds.to_xarray()