这里提供了一个玩具数据集,源自此处:
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()
的变量中减去月平均值的方法,如下所示:
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()
创建位置-月份数据,但它只允许传递维度;我可以使用 time.month
提取月份值,但它们被恢复为一个新变量,而不是一个维度。 我可以使用 for
或 xarray.DataSet.apply()
处理所有位置,但速度太慢了(我有大约65000个位置)。
期望的结果或过程类似于:
for each location:
climatology = ds.groupby("time.month").mean("time")
anomalies = ds.groupby("time.month") - climatology
最好的解决方案是仅使用xarray
,但如果使用pd.DataFrame()
或其他方法也可以实现快速解决,则这些解决方案也受欢迎。
编辑
以下是我当前使用`pd.DataFrame()`的解决方案:
# 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'])
apply_ufunc()
内计算的tmin的平均值与通过tmin数组计算的平均值(即np.mean(ds.tmin.values))进行比较,并发现它们并不完全相同(例如,对于2000年1月,-5.16275与-5.34013)。您能否详细说明一下这个问题? - hlee(ds.tmin - anomalies.tmin).sel(time='2000-01-01', location='IA')
和ds.isel(time=(ds.time.dt.month==1)).mean('time').sel(location='IA')
,两者都给出了相同的结果(-5.16275)。 - Agustín Begue