这是一个使用fill_between
绘图函数和 x 轴单位的解决方案,以便可以独立于 DatetimeIndex 和数据的频率突出显示周末。
x 轴范围用于计算图所涵盖的时间范围,以天为单位,这是matplotlib 日期使用的单位。然后weekends
计算掩码并将其传递给函数的where
参数fill_between
。掩码作为右排他处理,因此在这种情况下,它们必须包含星期一,以便在星期一 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);

您可以在我在此处和此处发布的答案中找到此解决方案的更多示例。