首页 > 解决方案 > 多年时间序列在python中具有阴影范围

问题描述

我有这些图表是我在 Excel 中从如下结构的数据框创建的:

在此处输入图像描述

以便可以像这样创建图表,将区域堆叠在5-Year Range范围顶部Min(无填充),以便可以对范围区域进行着色。min/max/range/avg 列都是从 2016-2020 年开始计算的。

5 年范围图

我知道我可以通过使用日期索引和应用月份标签在同一轴上绘制多年的线条,但是有没有办法复制此图表的阴影,更具体地说,如果我的数据框位于简单的日期索引值中格式,像这样:

            Quantity
1/1/2016    6
2/1/2016    4
3/1/2016    1
4/1/2016    10
5/1/2016    7
6/1/2016    10
7/1/2016    10
8/1/2016    2
9/1/2016    1
10/1/2016   2
11/1/2016   3
…   …
1/1/2020    4
2/1/2020    8
3/1/2020    3
4/1/2020    5
5/1/2020    8
6/1/2020    6
7/1/2020    6
8/1/2020    7
9/1/2020    8
10/1/2020   5
11/1/2020   4
12/1/2020   3
1/1/2021    9
2/1/2021    7
3/1/2021    7

我无法在绘图库中找到任何类似的东西。

标签: pythonpandasmatplotlib

解决方案


两步过程

  1. 重构 DF,使年份为列,行由统一的日期时间索引
  2. 使用matplotlib绘图
import datetime as dt
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

# straight date as index, quantity as column
d = pd.date_range("1-Jan-2016", "1-Mar-2021", freq="MS")
df = pd.DataFrame({"Quantity":np.random.randint(1, 10, len(d))}, index=d)


# re-structure as multi-index, make year column
# add calculated columns
dfg = (df.set_index(pd.MultiIndex.from_arrays([df.index.map(lambda d: dt.date(dt.date.today().year, d.month, d.day)), 
                                               df.index.year], names=["month","year"]))
 .unstack("year")
 .droplevel(0, axis=1)
 .assign(min=lambda dfa: dfa.loc[:,[c for c in dfa.columns if dfa[c].count()==12]].min(axis=1),
         max=lambda dfa: dfa.loc[:,[c for c in dfa.columns if dfa[c].count()==12]].max(axis=1),
         avg=lambda dfa: dfa.loc[:,[c for c in dfa.columns if dfa[c].count()==12]].mean(axis=1).round(1),
        )
)

fig, ax = plt.subplots(1, figsize=[14,4])

# now plot all the parts
ax.fill_between(dfg.index, dfg["min"], dfg["max"], label="5y range", facecolor="oldlace")
ax.plot(dfg.index, dfg[2020], label="2020", c="r")
ax.plot(dfg.index, dfg[2021], label="2021", c="g")
ax.plot(dfg.index, dfg.avg, label="5 yr avg", c="y", ls=(0,(1,2)), lw=3)

# adjust axis
ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b'))
ax.legend(loc = 'best')

在此处输入图像描述


推荐阅读