这是一个使用 fill_between 绘图函数和 x 轴单位的解决方案,以便可以独立于 DatetimeIndex 和数据频率突出显示周末。
x 轴范围用于以天为单位计算绘图所涵盖的时间范围,这是matplotlib dates 使用的单位。然后计算weekends 掩码并将其传递给fill_between 函数的where 参数。掩码作为右排他处理,因此在这种情况下,它们必须包含星期一,以便在星期一 00:00 之前绘制亮点。由于绘制这些高光可能会在周末发生在边界附近时改变 x 轴范围,因此绘制后 x 轴范围将设置回原始值。
请注意,与axvspan 不同,fill_between 函数需要y1 和y2 参数。出于某种原因,使用默认的 y 轴限制会在图框与周末亮点的顶部和底部之间留下一个小间隙。这个问题可以通过在创建绘图后运行ax.set_ylim(*ax.get_ylim()) 来解决。
这是一个基于提供的示例代码并使用类似于 jwalton 提供的答案的扩展数据集的完整示例:
import numpy as np # v 1.19.2
import pandas as pd # v 1.1.3
import matplotlib.pyplot as plt # v 3.3.2
import matplotlib.dates as mdates
# Create sample dataset
dt = pd.to_datetime(['2020-01-01', '2020-01-02', '2020-01-04', '2020-01-05',
'2020-01-06', '2020-01-07', '2020-01-09', '2020-01-10',
'2020-01-11', '2020-01-14'])
df = pd.DataFrame(dict(foo=range(len(dt))), index=dt)
# Draw pandas plot: setting x_compat=True converts the pandas x-axis units to
# matplotlib date units. This is not necessary for this particular example but
# it is necessary for all cases where the dataframe contains a continuous
# DatetimeIndex (for example ones created with pd.date_range) that uses a
# frequency other than daily
ax = df['foo'].plot(x_compat=True, figsize=(6,4), ylabel='foo')
ax.set_ylim(*ax.get_ylim()) # reset y limits to display highlights without gaps
# Highlight weekends based on the x-axis units
xmin, xmax = ax.get_xlim()
days = np.arange(np.floor(xmin), np.ceil(xmax)+2) # range of days in date units
weekends = [(dt.weekday()>=5)|(dt.weekday()==0) for dt in mdates.num2date(days)]
ax.fill_between(days, *ax.get_ylim(), where=weekends, facecolor='k', alpha=.1)
ax.set_xlim(xmin, xmax) # set limits back to default values
# Create and format x tick for each data point
plt.xticks(df.index.values, df.index.strftime('%d\n%a'), rotation=0, ha='center')
plt.title('Weekends are highlighted from SAT 00:00 to MON 00:00', pad=15, size=12);
您可以在我发布的here 和here 的答案中找到此解决方案的更多示例。