如何将每日数据绘制为月平均值(不同年份)

How to plot daily data as monthly averages (for separate years)

我正在尝试绘制一个图表来表示从 1980 年 1 月 1 日到 2013 年 12 月 31 日的每月河流流量数据集。

请查看这个graph

计划将“Jan Feb Mar Apr May...Dec”绘制为 x 轴,将流量 (m3/s) 绘制为 y 轴。图表上的实际线条将代表年份。或者,图表上的线条将显示从 1980 年到 2013 年每年的月平均值(从 1 月到 12 月)。

  DAT = pd.read_excel('Modelled Discharge_UIB_1980-2013_Daily.xlsx',
                   sheet_name='Karhmong', header=None, skiprows=1,
                    names=['year', 'month', 'day', 'flow'],
                    parse_dates={ 'date': ['year', 'month', 'day'] },
                   index_col='date') 

上面是显示是什么类型的数据


date        flow
1980-01-01  104.06
1980-01-02  103.81
1980-01-03  103.57
1980-01-04  103.34
1980-01-05  103.13
... ...
2013-12-27  105.65
2013-12-28  105.32
2013-12-29  105.00
2013-12-30  104.71
2013-12-31  104.42

因为我想比较所有年份所以我尝试了下面的命令

DAT1980 = DAT[DAT.index.year==1980]
DAT1980
DAT1981 = DAT[DAT.index.year==1981
DAT1981

...等等

就 x 轴的月份分组而言,我尝试使用命令

对月份进行分组
datmonth = np.unique(DAT.index.month)

到目前为止所有这些命令都没有导致错误

然而,当我绘制图表时,我得到了这个错误

图表绘图命令

fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(12,6))

ax.plot(datmonth, DAT1980, color='purple', linestyle='--', label='1980')
ax.grid()

plt.legend()

ax.set_title('Monthly River Indus Discharge Comparison 1980-2013')
ax.set_ylabel('Discharge (m3/s)')
ax.set_xlabel('Month')
axs.set_xlim(3, 5)


axs.xaxis.set_major_formatter
fig.autofmt_xdate()
ax.legend(loc='upper left', bbox_to_anchor=(1, 1))

我得到“ValueError:x 和 y 必须具有相同的第一维,但具有形状 (12,) 和 (366, 1)”作为错误

然后我尝试了

fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(12,6))

ax.plot(DAT.index.month, DAT.index.year==1980, color='purple', linestyle='--', label='1980')
ax.grid()

ax.plot(DAT.index.month, DAT.index.year==1981, color='black', marker='o', linestyle='-', label='C1981')
ax.grid()


plt.legend()

ax.set_title('Monthly River Indus Discharge Comparison 1980-2013')
ax.set_ylabel('Discharge (m3/s)')
ax.set_xlabel('Month')
#axs.set_xlim(1, 12)


axs.xaxis.set_major_formatter
fig.autofmt_xdate()
ax.legend(loc='upper left', bbox_to_anchor=(1, 1))

它比之前的图表效果更好,但仍然不是我想要的 (please check out the graph here)

因为我的意图是创建一个类似于 this

的图表

我衷心感谢您的任何建议!非常感谢,如果您需要任何进一步的信息,请随时询问,我会尽快回复。

欢迎来到 SO!干得好,清楚地描述了您的问题并显示了大量代码:)

这里和那里存在一些语法问题,但我看到的主要问题是您需要在某些时候添加 groupby/aggregation 操作。也就是说,您有每日数据,但您想要的图有每月分辨率(每年)。听起来你想要每年每个月的每日值的平均值(如果有误请纠正我)。

这是一些假数据:

dr = pd.date_range('01-01-1980', '12-31-2013', freq='1D')
flow = np.random.rand(len(dr))
df = pd.DataFrame(flow, columns=['flow'], index=dr)

看起来像你的例子:

                flow
1980-01-01  0.751287
1980-01-02  0.411040
1980-01-03  0.134878
1980-01-04  0.692086
1980-01-05  0.671108
             ...
2013-12-27  0.683654
2013-12-28  0.772894
2013-12-29  0.380631
2013-12-30  0.957220
2013-12-31  0.864612

[12419 rows x 1 columns]

您可以使用 groupby 获取每个月的平均值,使用您在上面使用的相同日期时间属性(使用一些额外的方法来帮助使数据更易于使用)

monthly = (df.groupby([df.index.year, df.index.month])
           .mean()
           .rename_axis(index=['year', 'month'],)
           .reset_index())

monthly有每年每个月的流量数据,即你要绘制的内容:

     year  month      flow
0    1980      1  0.514496
1    1980      2  0.633738
2    1980      3  0.566166
3    1980      4  0.553763
4    1980      5  0.537686
..    ...    ...       ...
403  2013      8  0.402805
404  2013      9  0.479226
405  2013     10  0.446874
406  2013     11  0.526942
407  2013     12  0.599161

[408 rows x 3 columns]

现在要绘制单个年份,您可以从 monthly 对其进行索引并绘制流量数据。我使用你的大部分坐标轴格式:

# make figure
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(12,6))

# plotting for one year
sub = monthly[monthly['year'] == 1980]
ax.plot(sub['month'], sub['flow'], color='purple', linestyle='--', label='1980')

# some formatting
ax.set_title('Monthly River Indus Discharge Comparison 1980-2013')
ax.set_ylabel('Discharge (m3/s)')
ax.set_xlabel('Month')
ax.set_xticks(range(1, 13))
ax.set_xticklabels(['J','F','M','A','M','J','J','A','S','O','N','D'])
ax.legend()
ax.grid()

生成以下内容:

您可以使用某种循环来绘制几年:

years = [1980, 1981, 1982, ...]
for year in years:
    sub = monthly[monthly['year'] == year]
    ax.plot(sub['month'], sub['flow'], ...)

你们 运行 遇到了一些其他挑战(比如找到一种方法来为 30 多行设置漂亮的样式,并在循环中这样做)。如果您无法通过此处的其他 post 找到如何完成某些事情,您可以打开一个新的 post(在此基础上构建)。祝你好运!