每年绘制 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 轴上的变量的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 y 轴上的百分比和 x 轴上的每个指标来绘制性能百分比?
pyqtgraph:如何绘制时间序列(x 轴上的日期和时间)?
绘制虚拟变量时,如何将 x 轴上的 0.0,1.0 更改为男性女性?