每年绘制 X 轴上的月份和来自 NetCDF 的 Y 轴上的变量

Posted

技术标签:

【中文标题】每年绘制 X 轴上的月份和来自 NetCDF 的 Y 轴上的变量【英文标题】:Plot every year as line with months on Xaxis and variable on Y-axis from NetCDF 【发布时间】:2021-07-24 11:09:54 【问题描述】:

我有以纬度、经度、时间为维度和温度temp 作为变量的 netcdf 数据。它有10年的每日温度数据。

对于单个位置,我可以绘制时间序列。但是如何在 X 轴上绘制每年,Year 和 Months 和 Y 轴上的 temp。所以我想在我的图表上用 10 条线作为 10 年。每条线是一年,代表 12 个月的平均值或每日数据。 example is here.

如果可能,请告诉如何在这 10 个年度线图中添加所有年份的平均值和中位数作为单独的线。示例图片image example

【问题讨论】:

这个问题需要更多的关注。到目前为止,您实际上做了什么?您是否需要代码才能以正确的格式获取数据以进行绘图?您是否希望有人为您编写此代码,或者您是否已经到此为止并被卡住了? 我已经通过空间均值将 3D 数组转换为 2D 并将其转换为 Pandas 2D 数据帧并用 Pandas 解决了绘图问题。但我想学习,完全在 Xarray 中做。 Huite Bootsma 下面的例子,给了我很多信息。 如果这是真的,您应该在问题中包含这一点,因为当您要求人们编写代码时就会出现问题,这不是 SO 的意义 【参考方案1】:

我很想同意这样的评论,即根据您的尝试表现出更多的努力会很好。最好提及您阅读的内容(例如 xarray 文档:https://xarray.pydata.org/en/stable/),我相信其中包含您需要的许多组件。

我将首先设置一些模拟数据,就像你提到的那样,包含四年的每日(随机)数据。

time = pd.date_range("2000-01-01", "2004-12-31")
base = xr.DataArray(
    data=np.ones((time.size, 3, 2)),
    dims=("time", "lat", "lon"),
    coords=
        "time": time,
        "lat": [1, 2, 3],
        "lon": [0.5, 1.5],
    ,
)

为了使数据与您的示例更具可比性,我将添加年度季节性(基于一年中的某天),并使每年增加 0.1。

seasonality = xr.DataArray(
    data=np.sin((time.dayofyear / 365.0) * (2 * np.pi)),
    coords="time": time,
    dims=["time"],
)
trend = xr.DataArray(
    data=(time.year - 2000) * 0.1,
    coords="time": time,
    dims=["time"],
)
da = base + seasonality + trend

(您显然可以跳过这两个部分,在您的情况下,您只需执行xarray.open_dataset() or xarray.open_dataarray`)

我不认为您的示例是按月份分组的:它太顺利了。因此,我将改为按年分组。 让我们从获取单个位置开始,然后使用 dt 访问器: https://xarray.pydata.org/en/stable/time-series.html#datetime-components

在这种情况下,将数据存储为 DataFrame 也是最方便的,因为它本质上变成了一个表(以一年中的月份为行,单独的年份等为列)。首先我们选择一个位置,计算最小值和最大值并将它们存储在 pandas DataFrame 中:

location = da.isel(lat=0, lon=0)
dataframe = location.groupby(da["time"].dt.dayofyear).min().drop(["lat", "lon"]).to_dataframe(name="min")
dataframe["max"] = location.groupby(da["time"].dt.dayofyear).max().values

接下来,逐年抓取数据,并将其添加到 DataFrame:

for year, yearda in location.groupby(location["time"].dt.year):
    dataframe[year] = pd.Series(index=yearda["time"].dt.dayofyear, data=yearda.values)

如果您想要每月值,请按步骤添加另一个分组:

for year, yearda in location.groupby(location["time"].dt.year):
    monthly_mean = yearda.groupby(yearda["time"].dt.month).mean()
    dataframe[year] = pd.Series(index=monthly_mean["month"], data=monthly_mean.values)

请注意,通过首先将数据转换为 pandas Series,它可以根据索引的值(此处为 dayofyear)适当地添加值,即使我们没有每年的 366 个值。

接下来,绘制它:

dataframe.plot()

它会根据列自动分配色调。

(由于我设置模拟数据的方式,我的最小值和最大值与 2000 年和 2004 年一致,......你明白了。)

在样式、选项等方面,你可能更喜欢 seaborn:

https://seaborn.pydata.org/index.html

import seaborn as sns
sns.plot(data=dataframe)

如果您想使用不同的样式、不同类型的图(例如您的示例具有的彩色区域),您必须组合不同的图,例如如下:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.fill_between(x=dataframe.index, y1=dataframe["min"], y2=dataframe["max"], alpha=0.5, color="orange")
dataframe.plot(ax=ax)

请注意,seaborn、pandas、xarray 等都在后台使用 matplotlib。许多绘图函数还接受 ax 参数,以在现有绘图的顶部绘图。

【讨论】:

非常感谢Huite Bootsma,这个例子对理解Xarray如何读取数据以及如何分离数据很有帮助。

以上是关于每年绘制 X 轴上的月份和来自 NetCDF 的 Y 轴上的变量的主要内容,如果未能解决你的问题,请参考以下文章

如何沿 x 轴均匀地绘制日期数据?

如何使用 y 轴上的百分比和 x 轴上的每个指标来绘制性能百分比?

pyqtgraph:如何绘制时间序列(x 轴上的日期和时间)?

绘制虚拟变量时,如何将 x 轴上的 0.0,1.0 更改为男性女性?

使用 ggplot 在折线图中仅绘制 x 轴上的日期向量的值

如何使用 Python 连接来自多个 netCDF 文件的数据