每年在 X 轴上绘制月份,在 NetCDF 的 Y 轴上绘制变量
Plot every year as line with months on Xaxis and variable on Y-axis from NetCDF
我有 netcdf 数据,维度为纬度、经度、时间,变量为温度 temp
。它有10年的每日温度数据。
对于单个位置,我可以绘制时间序列。但是如何绘制每一年,Year 作为色调,X 轴上的月份和 Y 轴上的 temp
。所以我想在我的图表上用 10 行作为 10 年。每条线都是一年,代表 12 个月的平均值或每日数据。 example is here.
如果可能的话,请告诉我如何在这 10 个年度线图中添加所有年份的平均值和中位数作为单独的线。示例图片 image example
我很想同意这样的评论,即在您尝试过的内容上表现出更多的努力会更好。最好提及您已阅读的内容(例如 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 也是最方便的,因为它实际上变成了 table(年月日作为行,单独的年等作为列)。首先我们 select 一个位置,计算最小值和最大值并将它们存储在 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 系列,它可以根据索引值(此处为 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
参数,以在现有绘图之上绘制。
我有 netcdf 数据,维度为纬度、经度、时间,变量为温度 temp
。它有10年的每日温度数据。
对于单个位置,我可以绘制时间序列。但是如何绘制每一年,Year 作为色调,X 轴上的月份和 Y 轴上的 temp
。所以我想在我的图表上用 10 行作为 10 年。每条线都是一年,代表 12 个月的平均值或每日数据。 example is here.
如果可能的话,请告诉我如何在这 10 个年度线图中添加所有年份的平均值和中位数作为单独的线。示例图片 image example
我很想同意这样的评论,即在您尝试过的内容上表现出更多的努力会更好。最好提及您已阅读的内容(例如 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 也是最方便的,因为它实际上变成了 table(年月日作为行,单独的年等作为列)。首先我们 select 一个位置,计算最小值和最大值并将它们存储在 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 系列,它可以根据索引值(此处为 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
参数,以在现有绘图之上绘制。