Skip to course content
Free data visualization course

Data Visualization and Dashboard Storytelling

Unit 05.04: Forecasts and how to draw the uncertainty

A forecast drawn like an actual will be read as a fact.

The interval widens; say so

Four actual periods and three forecast periods with widening intervals.

The code shows the widths.

ACTUAL = [100, 104, 109, 113]
FORECAST = [117, 121, 125]
INTERVAL = [(112, 122), (112, 130), (110, 140)]

print(f"{'period':>7} {'value':>8} {'range':>16} {'width':>7}")
for i, v in enumerate(ACTUAL, 1):
    print(f"{i:>7} {v:>8} {'actual':>16} {'':>7}")
for i, (v, (lo, hi)) in enumerate(zip(FORECAST, INTERVAL), len(ACTUAL) + 1):
    print(f"{i:>7} {v:>8} {f'{lo}-{hi}':>16} {hi - lo:>7}")

print("""
The interval widens from 10 to 30 as the horizon extends. A forecast drawn as
a single line, in the same style as the actuals, tells the reader none of that
-- and they will read the last point as a fact.

Draw the forecast in a different style, shade the interval, and mark where the
actuals stop.
""")

The interval triples across three periods. Drawn as a single line in the same style as the actuals, none of that reaches the reader - and the last point is the one that gets quoted.

Three things fix it: a different line style for the forecast, a shaded band for the interval, and a visible mark where the actuals stop.

The mistake this prevents

The mistake is showing the central estimate because the interval "looks uncertain". That is precisely the information the reader needs to decide how much weight to put on it - hiding it does not make the forecast more accurate, only more likely to be believed.

Takeaway

Draw forecasts in a different style, shade the interval, and mark where the actuals end. The interval is the useful part, not the caveat.