NetCDF数据绘图求助:2017-2023年逐年变量绘图未达预期
问题描述
我有一份包含2017-2023年数据的NetCDF文件,需求是将数据集按年份分组,绘制每个变量的月度图表。当前运行代码后仅生成单幅图,但预期得到2017-2023年的多幅逐年绘图。
我的Python代码如下:
%matplotlib inline import numpy as np import xarray as xr import pandas as pd import matplotlib.pyplot as plt import datetime as dt ds_smap = xr.open_dataset('SPL4SMGP.006_9km_aid0001.nc') #Select Location Alice Springs Mulga location = ds_smap.sel(lat = -22.2828,lon = 133.2493, day_period = 1, method='nearest') dataframe = location.groupby(ds_smap["time"].dt.dayofyear).min().drop(["lat", "lon"]).to_dataframe() dataframe["max"] = location.groupby(ds_smap["time"].dt.dayofyear).max().values for year, yearloc in location.groupby(location["time"].dt.year): dataframe[year] = pd.Series(index=yearloc["time"].dt.dayofyear, data=yearloc.values) dataframe['Geophysical_Data_sm_rootzone'].plot()
当前输出的单幅图:
解决建议
问题根源
循环中每次调用plot()时未指定新的绘图对象,所有年份数据都叠加绘制在了同一个图表上,导致仅显示单幅图。同时原代码转DataFrame的处理方式冗余,用xarray原生方法可更高效完成分组与绘图。
优化后的代码方案
%matplotlib inline import numpy as np import xarray as xr import matplotlib.pyplot as plt # 打开数据集 ds_smap = xr.open_dataset('SPL4SMGP.006_9km_aid0001.nc') # 选择目标位置 location = ds_smap.sel(lat=-22.2828, lon=133.2493, day_period=1, method='nearest') # 按年份分组 grouped = location.groupby('time.year') # 获取年份列表与需要绘制的变量(排除坐标变量) years = list(grouped.groups.keys()) variables = [var for var in location.data_vars if var not in ['lat', 'lon']] # 创建子图网格,每个年份对应一个子图 fig, axes = plt.subplots(nrows=len(years), ncols=1, figsize=(10, 3*len(years)), sharex=True) axes = axes.ravel() # 兼容单年份的情况,确保axes为一维数组 for idx, (year, year_data) in enumerate(grouped): ax = axes[idx] # 绘制该年份所有变量的时序图 year_data[variables].plot(ax=ax, linewidth=1.5) ax.set_title(f'Year: {year}') ax.set_xlabel('Month') ax.legend(loc='upper right') plt.tight_layout() plt.show()
关键改进点
- 用
xarray原生的groupby('time.year')分组,避免手动转DataFrame的冗余操作 - 创建子图网格,为每个年份分配独立的绘图区域,确保每一年的数据单独展示
- 自动遍历所有非坐标变量,一次性完成多变量绘图;若只需绘制特定变量,可将
variables改为['Geophysical_Data_sm_rootzone'] - 用
tight_layout()自动调整子图间距,提升可视化美观度
月度统计图表补充
如果需要绘制每月均值/最值的统计图表,可在年份分组后再按月份聚合:
for idx, (year, year_data) in enumerate(grouped): ax = axes[idx] # 按月份分组计算均值 monthly_data = year_data.groupby('time.month').mean() monthly_data[variables].plot(ax=ax, marker='o', linestyle='-') ax.set_title(f'Monthly Averages - Year: {year}') ax.set_xlabel('Month') ax.set_xticks(range(1,13)) ax.set_xticklabels(['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'])
内容的提问来源于stack exchange,提问作者Xei
相关产品推荐
相关产品推荐

