You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用xarray计算多年间每年同日的变量均值(特定时段处理)

问题描述

我有一个xarray DataArray,包含1970年至2023年10月至3月的每日数据,想计算变量每年同日的平均值(比如所有1月1日的平均值)。数据结构如下:

<xarray.DataArray 'u' (valid_time: 9990, latitude: 321, longitude: 361)> Size: 5GB
dask.array<getitem, shape=(9990, 321, 361), dtype=float32, chunksize=(260, 161, 181), chunktype=numpy.ndarray>
Coordinates:
    number          int64 8B 0
    pressure_level  float64 8B 500.0
  * latitude        (latitude) float64 3kB 0.0 -0.25 -0.5 ... -79.5 -79.75 -80.0
  * longitude       (longitude) float64 3kB -100.0 -99.75 -99.5 ... -10.25 -10.0
  * valid_time      (valid_time) datetime64[ns] 80kB 1970-01-01 ... 2023-12-31

我试过用groupby方法,但只能单独按月份或日期分组(比如所有月份的1日),没法同时按月份和日期分组。嵌套分组的方式能得到目标数据,但不够优雅:

da.groupby('valid_time.month')[1].groupby('valid_time.day')[1]

还参考了方法尝试用字符串格式化分组,结果报错:

da.groupby(da.index.strftime('%m-%d')).mean()

报错信息:

AttributeError: 'DataArray' object has no attribute 'index'

期望结果形状为(D, latitude, longitude),其中D是10月1日至3月31日的天数(已排除所有2月29日)。


解决方案

方法1:按月份+日期组合分组

xarray的groupby支持传入多个坐标属性的元组,直接实现“月-日”组合分组:

# 按月份和日期的组合分组,计算同日平均值
da_clim = da.groupby(['valid_time.month', 'valid_time.day']).mean()

# 筛选10-3月的数据,并排除2月29日
mask = (da_clim.month >= 10) | (da_clim.month <= 3)
mask = mask & ~((da_clim.month == 2) & (da_clim.day == 29))
da_clim_filtered = da_clim.where(mask, drop=True)

方法2:利用时间坐标的dt.strftime生成标签

之前报错是因为误操作了DataArray本身,应该直接对valid_time坐标的dt属性调用strftime:

# 生成"月-日"格式的字符串标签,用于分组
month_day = da.valid_time.dt.strftime('%m-%d')
da_clim = da.groupby(month_day).mean()

# 生成目标日期列表(10-3月,排除2月29日)
target_days = []
for m in [10,11,12,1,2,3]:
    max_day = 31 if m in [1,3,10,12] else 30 if m in [11] else 28
    for d in range(1, max_day+1):
        target_days.append(f"{m:02d}-{d:02d}")

# 筛选目标日期的数据
da_clim_filtered = da_clim.sel(valid_time=target_days)

方法3:用dayofyear分组(兼容闰年)

先排除2月29日的数据,再按年积日分组计算平均值,最后筛选目标日期范围:

# 先移除所有2月29日的数据
da_no_leap = da.where(~((da.valid_time.dt.month == 2) & (da.valid_time.dt.day == 29)), drop=True)
# 按年积日分组计算平均
da_clim = da_no_leap.groupby('valid_time.dayofyear').mean()

# 筛选10月1日(年积日274)至3月31日(年积日90)的数据
mask = (da_clim.dayofyear >= 274) | (da_clim.dayofyear <= 90)
da_clim_filtered = da_clim.where(mask, drop=True)

内容的提问来源于stack exchange,提问作者Ramiro chalar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 18:22:28