0
0
Matplotlibdata~15 mins

Custom legend entries in Matplotlib - Deep Dive

Choose your learning style9 modes available
Overview - Custom legend entries
What is it?
Custom legend entries in matplotlib allow you to create legends that do not directly correspond to plotted data. Instead of automatically using labels from plotted lines or markers, you can define your own legend items with specific symbols and text. This helps make your charts clearer and more informative by highlighting important categories or explanations.
Why it matters
Without custom legend entries, legends only show what is directly plotted, which can be confusing or incomplete. Custom legends let you explain your chart better, especially when you want to add extra information or group data differently. This improves communication and helps others understand your visual story quickly.
Where it fits
Before learning custom legend entries, you should know how to create basic plots and legends in matplotlib. After mastering custom legends, you can explore advanced visualization techniques like interactive plots or combining multiple plot types with clear explanations.
Mental Model
Core Idea
A custom legend entry is a manually created symbol and label that you add to a plot's legend to explain or highlight information not automatically included.
Think of it like...
It's like making your own key for a treasure map, where you draw symbols and write what they mean, instead of just using the map's default markings.
Plot area
┌─────────────────────────────┐
│                             │
│   ●   ○   ▲   ■             │  <-- plotted symbols
│                             │
│ Legend:                     │
│ ┌───────────────┐           │
│ │ ● Apples      │  <-- custom legend entries
│ │ ○ Oranges     │
│ │ ▲ Pears       │
│ │ ■ Unknown     │
│ └───────────────┘           │
└─────────────────────────────┘
Build-Up - 7 Steps
1
FoundationBasic legend creation in matplotlib
🤔
Concept: How to add a simple legend to a plot using labels from plotted data.
import matplotlib.pyplot as plt x = [1, 2, 3] y1 = [2, 3, 4] y2 = [4, 3, 2] plt.plot(x, y1, label='Line 1') plt.plot(x, y2, label='Line 2') plt.legend() plt.show()
Result
A plot with two lines and a legend showing 'Line 1' and 'Line 2' labels.
Understanding how matplotlib automatically uses labels from plotted lines is the foundation for customizing legends later.
2
FoundationUnderstanding legend handles and labels
🤔
Concept: Learn what legend handles and labels are and how matplotlib uses them to build legends.
fig, ax = plt.subplots() line1, = ax.plot([1, 2, 3], [2, 3, 4], label='A') line2, = ax.plot([1, 2, 3], [4, 3, 2], label='B') handles, labels = ax.get_legend_handles_labels() print(handles) print(labels)
Result
Output shows a list of line objects (handles) and their corresponding labels ['A', 'B'].
Knowing that legends are built from handles (symbols) and labels (text) lets you create custom legends by supplying your own.
3
IntermediateCreating custom legend entries manually
🤔Before reading on: do you think you can add a legend entry without plotting a line? Commit to yes or no.
Concept: You can create legend entries by making custom handles and labels without plotting them.
import matplotlib.patches as mpatches red_patch = mpatches.Patch(color='red', label='Red Area') plt.legend(handles=[red_patch]) plt.show()
Result
A legend with a red square and label 'Red Area' appears, even though no red patch is plotted.
Understanding that legend entries can be independent objects allows you to explain parts of your plot not directly drawn.
4
IntermediateUsing Line2D for custom line legend entries
🤔Before reading on: do you think you can create a custom legend entry that looks like a line without plotting it? Commit to yes or no.
Concept: Use matplotlib.lines.Line2D to create custom line symbols for legends.
from matplotlib.lines import Line2D custom_line = Line2D([0], [0], color='green', lw=2, linestyle='--', label='Dashed Green') plt.legend(handles=[custom_line]) plt.show()
Result
A legend shows a green dashed line labeled 'Dashed Green' without any line plotted.
Knowing how to create line-like legend entries helps you represent line styles or categories clearly.
5
IntermediateCombining plotted and custom legend entries
🤔Before reading on: do you think you can mix plotted lines and custom entries in one legend? Commit to yes or no.
Concept: You can combine handles from plotted data and custom handles to build a single legend.
line, = plt.plot([1, 2, 3], [3, 2, 1], label='Plotted Line') from matplotlib.lines import Line2D custom_line = Line2D([0], [0], color='purple', lw=2, linestyle=':', label='Custom Dotted') handles, labels = plt.gca().get_legend_handles_labels() handles.append(custom_line) labels.append('Custom Dotted') plt.legend(handles=handles, labels=labels) plt.show()
Result
Legend shows 'Plotted Line' and 'Custom Dotted' entries together.
Combining handles lets you enrich legends with extra information beyond plotted data.
6
AdvancedCustom legend entries with markers and styles
🤔Before reading on: can you create a legend entry with a custom marker shape and color without plotting it? Commit to yes or no.
Concept: Use Line2D with marker parameters to create custom legend entries with specific markers and styles.
from matplotlib.lines import Line2D custom_marker = Line2D([0], [0], marker='o', color='w', label='Circle Marker', markerfacecolor='orange', markersize=10) plt.legend(handles=[custom_marker]) plt.show()
Result
Legend shows an orange circle marker labeled 'Circle Marker' without any plotted points.
Custom markers in legends help explain symbols used in plots or add new symbolic meaning.
7
ExpertAdvanced control with proxy artists and legend handlers
🤔Before reading on: do you think you can fully customize legend appearance using proxy artists and handlers? Commit to yes or no.
Concept: Proxy artists are dummy objects used to create complex custom legend entries; legend handlers control how these are drawn.
import matplotlib.pyplot as plt from matplotlib.legend_handler import HandlerTuple from matplotlib.lines import Line2D line1 = Line2D([0], [0], color='blue', lw=2) line2 = Line2D([0], [0], color='red', lw=2) plt.legend([(line1, line2)], ['Blue & Red Lines'], handler_map={tuple: HandlerTuple(ndivide=None)}) plt.show()
Result
Legend shows a single entry with both blue and red lines side by side labeled 'Blue & Red Lines'.
Understanding proxy artists and handlers unlocks powerful legend customizations for complex visualizations.
Under the Hood
Matplotlib legends are built from 'handles' and 'labels'. Handles are objects representing symbols (lines, patches, markers). When you call plt.legend(), matplotlib collects handles and labels from plotted objects or those you provide. It then draws the legend box by rendering each handle with its label. Custom legend entries work by creating or supplying handles manually, which matplotlib treats like any plotted object for the legend.
Why designed this way?
This design separates the visual elements (handles) from their descriptions (labels), allowing flexibility. It lets matplotlib automatically generate legends from plots but also lets users override or extend legends with custom entries. This approach balances ease of use with power, avoiding rigid legend generation tied only to plotted data.
Legend Creation Flow
┌───────────────────────────────┐
│ User calls plt.legend()       │
│                               │
│ ↓                             │
│ Collect handles and labels     │
│ - From plotted objects         │
│ - From user-supplied handles   │
│                               │
│ ↓                             │
│ Draw legend box with entries   │
│ - Render each handle symbol    │
│ - Add corresponding label text │
└───────────────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Do you think legend entries must always match plotted data exactly? Commit yes or no.
Common Belief:Legend entries can only show labels from the data you have plotted.
Tap to reveal reality
Reality:You can create legend entries that do not correspond to any plotted data by making custom handles.
Why it matters:Believing this limits your ability to explain or clarify plots, reducing communication effectiveness.
Quick: Do you think you must plot something visible to create a legend entry? Commit yes or no.
Common Belief:You must plot a visible object to have a legend entry for it.
Tap to reveal reality
Reality:You can create invisible or proxy objects just for legend entries without plotting them.
Why it matters:This misconception prevents adding helpful legend explanations for abstract or combined concepts.
Quick: Do you think legend handles must be lines or patches only? Commit yes or no.
Common Belief:Legend handles can only be lines or patches from matplotlib.
Tap to reveal reality
Reality:Legend handles can be any artist object, including custom proxy artists or tuples of artists.
Why it matters:Knowing this allows advanced legend customization for complex visual storytelling.
Quick: Do you think legend labels must be unique? Commit yes or no.
Common Belief:Legend labels must be unique strings to work properly.
Tap to reveal reality
Reality:Labels can repeat or be the same; matplotlib handles duplicates but this can cause confusion if not managed.
Why it matters:Mismanaging labels can cause unclear legends or unexpected behavior in legend display.
Expert Zone
1
Custom legend entries can use tuples of artists to combine multiple symbols into one legend item, enabling complex explanations.
2
Legend handlers can be customized or subclassed to control exactly how legend entries are drawn, allowing for dynamic or interactive legends.
3
Invisible proxy artists can be used to represent abstract concepts or data groupings that do not have a direct visual representation in the plot.
When NOT to use
Avoid custom legend entries when the automatic legend clearly and simply represents your data. Overusing custom entries can confuse readers. For interactive or dynamic legends, consider using specialized visualization libraries like Plotly or Bokeh instead.
Production Patterns
In production, custom legend entries are used to explain combined data categories, represent missing or special data points, or clarify complex visual encodings. Teams often create reusable legend handle functions to maintain consistent legends across multiple plots.
Connections
Proxy pattern (software design)
Custom legend entries use proxy artists similar to the proxy pattern where a stand-in object represents another.
Understanding proxy objects in software helps grasp how matplotlib uses dummy artists to represent legend items without plotting them.
User interface design
Custom legends improve user interface clarity by providing tailored explanations and reducing cognitive load.
Knowing UI design principles helps create legends that communicate effectively and enhance user understanding.
Cartography (map legends)
Custom legend entries in plots serve the same purpose as map legends, explaining symbols and colors for better interpretation.
Recognizing this connection shows how visualization principles apply across fields to aid comprehension.
Common Pitfalls
#1Creating a legend entry without a proper handle object.
Wrong approach:plt.legend(handles=['Red Area'], labels=['Red Area'])
Correct approach:import matplotlib.patches as mpatches red_patch = mpatches.Patch(color='red', label='Red Area') plt.legend(handles=[red_patch])
Root cause:Passing strings instead of artist objects as handles causes matplotlib to fail drawing the legend symbol.
#2Forgetting to add custom handles to the existing handles list when combining legends.
Wrong approach:line, = plt.plot([1, 2, 3], [3, 2, 1], label='Line') custom_line = Line2D([0], [0], color='green', label='Custom') plt.legend(handles=[custom_line])
Correct approach:handles, labels = plt.gca().get_legend_handles_labels() handles.append(custom_line) labels.append('Custom') plt.legend(handles=handles, labels=labels)
Root cause:Overwriting the legend handles without including existing plotted handles removes original legend entries.
#3Using duplicate labels without managing them.
Wrong approach:plt.plot([1, 2], [3, 4], label='Data') plt.plot([1, 2], [4, 3], label='Data') plt.legend()
Correct approach:plt.plot([1, 2], [3, 4], label='Data 1') plt.plot([1, 2], [4, 3], label='Data 2') plt.legend()
Root cause:Duplicate labels cause confusion in the legend and may lead to unexpected legend behavior.
Key Takeaways
Custom legend entries let you add meaningful explanations to plots beyond what is automatically generated.
Legends are built from handles (symbols) and labels (text), and you can create both manually for full control.
Using proxy artists like Line2D or Patch objects allows you to design any symbol you want in the legend.
Combining plotted and custom handles in one legend enriches your plot's storytelling and clarity.
Advanced techniques like proxy artists and legend handlers enable complex, professional-quality legends.