Skip to course content
Free data visualization course

Data Visualization and Dashboard Storytelling

Unit 03.03: Legends, and why direct labelling beats them

A legend costs the reader a lookup for every series, every time they glance at the chart.

Four steps versus one

What the reader has to do to identify a line with a legend, and without.

The code counts the steps.

SERIES = ["North", "South", "East", "West"]
print("with a legend, the reader must:")
for step in ["find the line", "match its colour to the legend",
             "hold the name in memory", "return to the line"]:
    print(f"   {step}")

print("\nwith direct labels at the line ends, the reader must:")
print("   read the name next to the line")

print(f"\n{len(SERIES)} series: 4 lookup steps each with a legend, 1 without.")
print("Legends cost a lookup per series per glance. Direct labelling removes it.")

# Legends earn their place when series are too dense to label, or when the same
# legend serves several small charts. For four lines with room at the right,
# direct labels are strictly better.

Four series means four lookups per glance, and a glance is what most charts get. Direct labelling at the end of each line replaces all of it with reading a word that is already next to the thing it names.

Legends still earn their place when series are too dense to label, or when one legend serves several small panels. For four lines with room at the right, they are strictly worse.

The mistake this prevents

The mistake is treating the legend as mandatory because the tool produces one. It is a default, it costs the reader work, and removing it is usually two lines of code.

Takeaway

Direct-label the series where there is room. A legend costs a lookup per series per glance and is a default rather than a requirement.