Of course! This is a very common and important task when creating data visualizations in Python. The ggplot library is a port of R's famous ggplot2, and its syntax for legends is powerful and consistent.

Here’s a comprehensive guide to creating and customizing legends in Python's ggplot.
The Foundation: How Legends are Created
In ggplot, a legend is automatically generated whenever you use an aesthetic (aes()) that maps a variable to a visual property. The most common aesthetics that create legends are:
colororcolour: For points, lines, and fills.fill: For the inside of bars, polygons, etc.shape: For point markers.size: For the size of points or lines.linetype: For dashed/dotted lines.alpha: For transparency.
Key Concept: The legend is created based on the mapping inside aes(), not the setting outside of it.
Basic Example: Automatic Legend Creation
Let's start with a simple scatter plot where we map the species column to the color aesthetic. ggplot will automatically create a legend for us.

import pandas as pd
from plotnine import ggplot, aes, geom_point, labs
# Sample data (the famous Iris dataset)
from plotnine.data import mtcars
# For a more colorful example, let's use a built-in dataset
from plotnine.data import mpg
# Create the plot
# We map 'class' to color and 'displ' to size
plot = (
ggplot(mpg, aes(x='displ', y='hwy', color='class', size='cty'))
+ geom_point()
+ labs(
title="MPG Dataset",
x="Engine Displacement (L)",
y="Highway Miles Per Gallon",
color="Vehicle Class", # Custom legend title for color
size="City MPG" # Custom legend title for size
)
)
print(plot)
What's happening here?
aes(color='class'): This tellsggplotto use a different color for each unique value in theclasscolumn (e.g., "compact", "suv", "2seater"). This mapping is what triggers the legend to be created.labs(color='Vehicle Class'): This is used to give the legend a more descriptive title. You can uselabs()forcolor,fill,size,shape, etc.
Customizing the Legend Title
As shown above, you can set the legend title directly in labs().
from plotnine import ggplot, aes, geom_point, labs
plot = (
ggplot(mpg, aes(x='displ', y='hwy', color='class'))
+ geom_point()
+ labs(
title="Custom Legend Title",
color="Type of Car" # This changes the legend title for 'color'
)
)
print(plot)
Hiding a Legend
Sometimes you don't want a legend to appear. You have two main ways to do this.
Method A: Remove a Specific Legend
If you have multiple aesthetics mapped (e.g., color and size), you can remove just one of them.
from plotnine import ggplot, aes, geom_point, guides
plot = (
ggplot(mpg, aes(x='displ', y='hwy', color='class', size='cty'))
+ geom_point()
+ guides(color="none") # Hide the legend for the 'color' aesthetic
)
print(plot)
Method B: Hide All Legends
If you want to remove all legends from the plot at once, you can use theme().
from plotnine import ggplot, aes, geom_point, theme
plot = (
ggplot(mpg, aes(x='displ', y='hwy', color='class', size='cty'))
+ geom_point()
+ theme(legend_position="none") # The most direct way to hide all legends
)
print(plot)
Customizing Legend Items (Labels and Order)
This is a very common requirement. You want to change the text labels in the legend or reorder them.
Method A: Using scale_*_manual()
This is the most flexible and powerful method. You explicitly provide the labels and the order.
from plotnine import ggplot, aes, geom_point, scale_color_manual, labs
# Define the order and labels for the legend items
legend_order = ["suv", "compact", "pickup", "subcompact"]
legend_labels = ["SUV (Largest)", "Compact (Small)", "Pickup (Work)", "Subcompact (Tiny)"]
plot = (
ggplot(mpg, aes(x='displ', y='hwy', color='class'))
+ geom_point()
+ scale_color_manual(
name="Vehicle Type", # Legend title
labels=legend_labels, # Custom labels for each item
values=legend_order # The order of items in the legend
)
)
print(plot)
Note: In scale_color_manual, the values argument can also be used to assign specific colors. For example: values=["red", "blue", "green", "yellow"].
Method B: Using factor() and .cat.reorder()
If your data is in a pandas Categorical, you can reorder it directly, and ggplot will respect that order.
import pandas as pd
from plotnine import ggplot, aes, geom_point
# Create a Categorical type with a specific order
mpg['class'] = pd.Categorical(mpg['class'], categories=["pickup", "suv", "compact", "subcompact"], ordered=True)
plot = (
ggplot(mpg, aes(x='displ', y='hwy', color='class'))
+ geom_point()
)
print(plot)
# The legend will now be in the order: pickup, suv, compact, subcompact
Changing the Legend Position
By default, legends are placed on the right side of the plot. You can change this using the legend_position argument in theme().
"right"(default),"left","top","bottom""none"(to hide it, as seen before)- You can also use numeric coordinates like
(0.1, 0.9)for fine-grained control.
from plotnine import ggplot, aes, geom_point, theme
# Place legend at the bottom
plot_bottom = (
ggplot(mpg, aes(x='displ', y='hwy', color='class'))
+ geom_point()
+ theme(legend_position="bottom")
)
# Place legend in the top-left corner
plot_top_left = (
ggplot(mpg, aes(x='displ', y='hwy', color='class'))
+ geom_point()
+ theme(legend_position=(0.02, 0.98)) # x, y coordinates (0-1 range)
)
print(plot_bottom)
print(plot_top_left)
Modifying the Legend Appearance (Background, Box, Keys)
You can use the theme() function to control almost every aspect of the legend's appearance.
legend_key: The box around the legend symbol (e.g., the colored square).legend_background: The background of the entire legend box.legend_text: The text of the legend labels.legend_title: The text of the legend title.
from plotnine import ggplot, aes, geom_point, theme, element_blank, element_rect, element_text
plot = (
ggplot(mpg, aes(x='displ', y='hwy', color='class'))
+ geom_point()
+ theme(
legend_position="bottom",
legend_key=element_rect(fill="lightblue", color="black", size=0.5), # Add a border and fill to legend keys
legend_background=element_rect(fill="yellow", alpha=0.3), # Add a semi-transparent background to the whole legend
legend_text=element_text(color="purple", size=10), # Change label text color and size
legend_title=element_text(face="bold.italic", size=12, color="darkblue") # Style the title
)
)
print(plot)
Complete Example: Putting It All Together
Let's create a final, polished example that combines several of these techniques.
import pandas as pd
from plotnine import (
ggplot, aes, geom_point, geom_smooth,
scale_color_manual, labs, theme,
element_rect, element_text
)
# Sample data
df = pd.DataFrame({
'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'y': [2.1, 3.9, 6.2, 7.8, 10.1, 12.3, 13.8, 16. 