首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Python中减去每个网格的每月平均值的最佳方法

在Python中减去每个网格的每月平均值的最佳方法
EN

Stack Overflow用户
提问于 2021-04-01 10:59:00
回答 1查看 392关注 0票数 4

来自这里的玩具数据集

代码语言:javascript
复制
import numpy as np
import pandas as pd
import seaborn as sns

import xarray as xr

np.random.seed(123)

xr.set_options(display_style="html")

times = pd.date_range("2000-01-01", "2001-12-31", name="time")
annual_cycle = np.sin(2 * np.pi * (times.dayofyear.values / 365.25 - 0.28))

base = 10 + 15 * annual_cycle.reshape(-1, 1)
tmin_values = base + 3 * np.random.randn(annual_cycle.size, 3)
tmax_values = base + 10 + 3 * np.random.randn(annual_cycle.size, 3)

ds = xr.Dataset(
    {
        "tmin": (("time", "location"), tmin_values),
        "tmax": (("time", "location"), tmax_values),
    },
    {"time": times, "location": ["IA", "IN", "IL"]},
)

我知道这里,我可以找到如何从xarray.DataSet()中的变量中减去每月平均值,如下所示:

代码语言:javascript
复制
climatology = ds.groupby("time.month").mean("time")
anomalies = ds.groupby("time.month") - climatology
anomalies.mean("location").to_dataframe()[["tmin", "tmax"]].plot()

那么,我能为每个位置做减法吗?

我试着为位置月组做这件事,但是xarray.DataSet.groupby()不允许传递多个组。然后,我尝试使用xarray.DataSet.stack()创建location,但它只允许传递维度;我可以使用time.month提取月份值,但它们被还原为一个新变量,而不是维度。我可以对所有位置使用forxarray.DataSet.apply(),但速度太慢(我有大约65000个位置)。

预期的结果或过程类似于:

代码语言:javascript
复制
for each location:
    climatology = ds.groupby("time.month").mean("time")
    anomalies = ds.groupby("time.month") - climatology

只有xarray内部的解决方案是最好的,但是如果使用pd.DataFrame()或其他解决方案是可能的,而且速度相当快,那么这些解决方案也是受欢迎的。

编辑

下面是我使用`pd.DataFrame()的当前解决方案

代码语言:javascript
复制
# convert to pd.dataframe
df = ds.to_dataframe()

# get mean monthly values
months = df.index.get_level_values('time').month
df_meanMonths = df.groupby([pd.Grouper(level='location'), months]).mean()

# rename and reindex
df_meanMonths.rename(columns={'tmin': 'tminMM', 'tmax': 'tmaxMM'}, inplace=True)
df_meanMonths.index.set_names('month', level='time', inplace=True)

# merge
df['month'] = df.index.get_level_values('time').month
vars_join = ['tminMM', 'tmaxMM']
join_right = df_meanMonths[vars_join]

# results
df.reset_index().set_index(['location', 'month']).merge(join_right, how='left', left_index=True, right_on=['location', 'month'])
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-18 12:48:32

我想你可能想找的是:

代码语言:javascript
复制
anomalies = xr.apply_ufunc(
    lambda x, mean: x - mean, 
    ds.tmax.groupby('time.month'),
    ds.tmax.groupby('time.month').mean()
).drop('month')

仅用于tmax变量( DataArray)或

代码语言:javascript
复制
anomalies = xr.apply_ufunc(
    lambda x, means: x - means, 
    ds.groupby('time.month'),
    ds.groupby('time.month').mean()
).drop('month')

用于数据集中的所有变量。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66903278

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档