民宿入住率:70 天实测与未来四周预测
单位:周均入住率(%) / 模型:周季节项 + 残差自助法重采样 / 数据截至 2026-10-04
- 历史实测(蓝色实线)
- 模型预测(橙色虚线)
- 置信带(外层 95% / 内层 80%)
- 现在(历史与预测分界)
为什么置信带必须随距离张开
图注铁律:带宽是预测方差的直接投影。模型每向前走一步,季节项的估计误差、残差的累积与外部事件的未知扰动都会叠加,不确定性像利息一样复利增长——带若不张开,等于在视觉上谎报了模型的把握。
本例中带宽从「现在」这一点归零起步:一周后 95% 半宽仅 ±9 个百分点(国庆余温尚有近期数据约束),四周后张开到 ±20 个百分点(淡季基线本身的历史样本更少,长尾事件权重上升)。近端收窄、远端发散的扇形,正是「数据在说话、也在交出话语权」的形状。
如果两条带画成等宽的平行带,或远端反而收窄,读者会默认远期预测更可靠——这与任何真实模型的误差结构都相反。
两层带的分工
80% 带(内层,颜色更深)是运营决策的默认参照:排班、备货、定价都以「八成会落在这里」为底线。四周后的 80% 区间 44% 至 66%,意味着最悲观情形入住率不到一半,最乐观情形接近满房。
95% 带(外层,颜色更浅)是风险对话的素材:它诚实地承认极端情形。当 95% 下限逼近盈亏平衡线时,这张图就自动变成了「要不要推出淡季长住折扣」的论证材料。
两层同色异深、嵌套包含(95% 带永远覆盖 80% 带),是比彩虹色更克制也更不易误读的做法。
反例警示:裸预测的隐形承诺
同一条预测线,删掉置信带之后,性质就变了
去掉带之后,读者会本能地把虚线的末端当成承诺:第四周「就是 55%」。而原模型的 95% 区间其实是 35% 至 75%——宽到足以让「满房」和「半空」都属正常。裸预测把一个分布压缩成了一个点,所有下游讨论都会围绕这个不存在的确定性展开。
更隐蔽的代价:没有带,就没有人能质疑模型。置信带把「模型可能错多少」摆在桌面上,这恰恰是预测图获得信任的途径。
视觉编码规范
- 线实线 / 虚线是第一编码,颜色只是第二编码历史 #0080FF 实线、预测 #FF9500 虚线(8 比 7 短划)。色觉障碍读者、黑白打印下线型差异仍然成立。
- 带同色系透明度分层,禁止彩虹双带以 15% 透明度基准:95% 带单层约 13%,80% 带叠至约 22%–26%,嵌套包含关系一目了然。
- 标带直接标注在带内,不用图例转译「95% 置信带 / 80% 置信带」文字长在带上,视线不必在图例与图之间往返。
- 界「现在」必须有分界线细虚线加文字锚点,明确哪半边是事实、哪半边是推断——这是本图型的法律边界。
- 值点值必须伴随具名区间任何脱离区间单独出现的预测数字,都是对官方无障碍守则(色调单独不足)的违反。
与近亲图型的边界
同样是「区间 + 走势」,换一种场合就该换一种图。
- Ribbon Chart带状图 / 官方备选当需要并列比较多条序列各自的区间——两套模型、两个门店、两种定价方案——把置信带加细描边变成实心带并列排布,避免多组「线加带」交缠成面条汤。本例只有一条序列,折线加双带仍是更轻的选择。
- 区间柱状图预测节点少于四个、且节点是离散事件(季度指引、里程碑交付)时,柱形区间比折线带更诚实:折线会暗示节点之间存在连续轨迹,而季度指引之间并没有。
- 多分位带分布明显非对称或长尾(如爆红事件驱动的流量)时,对称置信带会系统性歪曲一侧,应改用 50% / 80% / 95% 分位带,点预测线换成中位数线,图注同步改口。
数据表后备:预测数值与区间
当图表无法呈现(读屏器、纯文本邮件、打印)时,本表即完整替身;行序与图中虚线点一一对应。
历史锚点:暑期峰值 75%(08-16 止一周)、淡季谷底 51%(09-13 止一周)、国庆周 83%(09-27 止一周)。表中所有区间满足 95% 区间完整包含 80% 区间。
不确定性摘要
取色与参数速查
官方选型数据(charts.json No.09)的直接转译,复制即用;两层带在交叠处自然加深,无需为 80% 带单设色值。
/* 图型 token / Line with Confidence Band */ --fc-actual: #0080FF; /* 历史实线 */ --fc-forecast: #FF9500; /* 预测虚线 */ --fc-band-95: rgba(255,149,0,.13); /* 95% 带,15% 基准的浅层 */ --fc-band-80: rgba(255,149,0,.22); /* 80% 带,叠加后视觉约 26% */ --fc-ink: #8A5C0E; /* 带上直接标注用深墨,白底对比 5.8:1 */ --fc-dash: 8 7; /* 预测虚线节奏,与实线拉开线型差 */ --fc-now: 1.4px dashed #26292E; /* 「现在」分界,2 比 4 短划 */ --fc-history-window: 30-90d; /* 历史窗口可读上限 */ --fc-horizon: 30%; /* 预测视界占可见横轴上限 */
实现落点:三个推荐库怎么落地置信带
Chart.js
无内置置信带,用边界线加区域填充组合
- 准备三条线:95% 上界、点预测、95% 下界各一个 dataset,上界与下界设
borderColor:'transparent',仅作填充骨架。 - 带填充:下界 dataset 设
fill:'+1'与backgroundColor:'rgba(255,149,0,.13)',80% 带同理叠一层更深的填充。 - 线型差异:历史线默认实线;预测线设
borderDash:[8,7],并把预测段单独拆成 dataset 以便整段切换显隐。 - 「现在」分界:自定义插件在 annotation 或
afterDraw里画竖直虚线并落文字。 - canvas 无障碍回退。Chart.js 画在 canvas 上对读屏不可见:容器加
role="img"与完整 aria-label,同时在文档流内保留可见数据表(即本页表格后备的做法),两道保险缺一不可。
Plotly
对不确定性编码支持最直接
- 边界成对:上界与下界各一条
scattertrace,上界设fill:'tonexty',带色即fillcolor。 - 双层嵌套:先画 95% 对再画 80% 对,内层后画自然覆盖在外层之上,包含关系零成本成立。
- 悬停合并:设
hovermode:'x unified',点值与两条区间边界的数值合并为一张浮卡,对应「具名区间」要求。 - 线型:预测 trace 设
line:{dash:'dash'},历史 trace 保持实线。
ApexCharts
用范围面积图承载带,思路最省力
- 带即 rangeArea:版本 3.26 起原生支持
rangeArea图型,一组[下界,上界]数据即成一带,两层各一组。 - 预测段拆 series:历史与预测拆成两个 line series,预测段开
dashArray:8,历史段置零。 - 点悬停:
tooltip.shared:true让点值与区间同屏;回调里给区间行加「80% / 95%」前缀文字。 - 注意:rangeArea 不参与 y 轴自动缩放的部分版本有坑,显式给
yaxis.min/max(本例 30 至 90)兜底。
无障碍走查:官方后备方案在本页的落实
键盘走查
- Tab 遍历数据点,焦点即数值。每个历史与预测数据点均可聚焦,聚焦浮卡与悬停浮卡同一份内容,不依赖指针设备。
- 按钮切换历史与预测。「仅看历史 / 显示预测」以
aria-pressed同步状态,屏幕上与读屏时都能得知当前显隐。 - 缩放与复位。「拉近近六周 / 拉远看全程」对应官方加減缩放语义,「复位」一键恢复全程视野与两组序列,焦点不丢失。
- 跳转链接。页首「跳到主内容」让键盘用户绕过面包屑与页头直达主图。
读屏 / 打印 / 色觉
- 图形有完整文字替身。主图为
role="img"且 aria-label 覆盖全部走势与区间结论;逐点数值另有可聚焦标签。 - 数据表即后备。预测表包含点值、80% 与 95% 区间、半宽与历史锚点,纯文本环境下信息零损失。
- 线型优先于色相。实线与虚线(8 比 7 短划)承担第一层区分,黑白打印与三类色觉障碍下均成立。
- 动效可退。预测段一次描边显现在
prefers-reduced-motion下直接呈现终态,不制造闪烁与位移。