Theming & Styling¶
Customize the appearance of your plots with built-in themes and custom styling options.
In [1]:
Copied!
import pandas as pd
import numpy as np
from ggplotly import *
df = pd.DataFrame({'x': range(1, 6), 'y': [2, 4, 3, 5, 4]})
base = ggplot(df, aes(x='x', y='y')) + geom_line() + geom_point(size=10)
base # Default theme
import pandas as pd
import numpy as np
from ggplotly import *
df = pd.DataFrame({'x': range(1, 6), 'y': [2, 4, 3, 5, 4]})
base = ggplot(df, aes(x='x', y='y')) + geom_line() + geom_point(size=10)
base # Default theme
Out[1]:
theme_minimal¶
Clean, minimal design:
In [2]:
Copied!
(base + theme_minimal() + labs(title='theme_minimal'))
(base + theme_minimal() + labs(title='theme_minimal'))
Out[2]:
theme_classic¶
Classic look with axis lines, no gridlines:
In [3]:
Copied!
(base + theme_classic() + labs(title='theme_classic'))
(base + theme_classic() + labs(title='theme_classic'))
Out[3]:
theme_dark¶
Dark background for high contrast:
In [4]:
Copied!
(base + theme_dark() + labs(title='theme_dark'))
(base + theme_dark() + labs(title='theme_dark'))
Out[4]:
theme_ggplot2¶
Mimic R's ggplot2 default appearance:
In [5]:
Copied!
(base + theme_ggplot2() + labs(title='theme_ggplot2'))
(base + theme_ggplot2() + labs(title='theme_ggplot2'))
Out[5]:
theme_bbc¶
BBC-style news graphics:
In [6]:
Copied!
(base + theme_bbc() + labs(title='theme_bbc'))
(base + theme_bbc() + labs(title='theme_bbc'))
Out[6]:
theme_nytimes¶
New York Times style:
In [7]:
Copied!
(base + theme_nytimes() + labs(title='theme_nytimes'))
(base + theme_nytimes() + labs(title='theme_nytimes'))
Out[7]:
In [8]:
Copied!
(ggplot(df, aes(x='x', y='y'))
+ geom_point(size=10)
+ theme(
plot_background=element_rect(fill='#f0f0f0'),
panel_background=element_rect(fill='white'),
axis_text=element_text(size=12, color='darkblue'),
axis_title=element_text(size=14, color='darkblue')
)
+ labs(title='Custom Theme'))
(ggplot(df, aes(x='x', y='y'))
+ geom_point(size=10)
+ theme(
plot_background=element_rect(fill='#f0f0f0'),
panel_background=element_rect(fill='white'),
axis_text=element_text(size=12, color='darkblue'),
axis_title=element_text(size=14, color='darkblue')
)
+ labs(title='Custom Theme'))
Out[8]:
Grid Customization¶
In [9]:
Copied!
(ggplot(df, aes(x='x', y='y'))
+ geom_point(size=10)
+ theme(
panel_grid_major=element_line(color='lightgray', width=1, dash='dash'),
panel_grid_minor=element_line(color='#f0f0f0', width=0.5),
axis_line=element_line(color='black', width=2)
)
+ labs(title='Custom Grid'))
(ggplot(df, aes(x='x', y='y'))
+ geom_point(size=10)
+ theme(
panel_grid_major=element_line(color='lightgray', width=1, dash='dash'),
panel_grid_minor=element_line(color='#f0f0f0', width=0.5),
axis_line=element_line(color='black', width=2)
)
+ labs(title='Custom Grid'))
Out[9]:
In [10]:
Copied!
df = pd.DataFrame({
'x': np.random.randn(100),
'y': np.random.randn(100),
'group': np.random.choice(['A', 'B'], 100)
})
# Position: 'top', 'bottom', 'left', 'right', 'none'
(ggplot(df, aes(x='x', y='y', color='group'))
+ geom_point()
+ theme(legend_position='top'))
df = pd.DataFrame({
'x': np.random.randn(100),
'y': np.random.randn(100),
'group': np.random.choice(['A', 'B'], 100)
})
# Position: 'top', 'bottom', 'left', 'right', 'none'
(ggplot(df, aes(x='x', y='y', color='group'))
+ geom_point()
+ theme(legend_position='top'))
Out[10]:
Hide Legend¶
In [11]:
Copied!
(ggplot(df, aes(x='x', y='y', color='group'))
+ geom_point()
+ theme(legend_position='none'))
(ggplot(df, aes(x='x', y='y', color='group'))
+ geom_point()
+ theme(legend_position='none'))
Out[11]:
Using guides() to Hide¶
In [12]:
Copied!
(ggplot(df, aes(x='x', y='y', color='group'))
+ geom_point()
+ guides(color='none'))
(ggplot(df, aes(x='x', y='y', color='group'))
+ geom_point()
+ guides(color='none'))
Out[12]:
guide_colorbar¶
Customize continuous color legends:
In [13]:
Copied!
df = pd.DataFrame({
'x': np.random.rand(100),
'y': np.random.rand(100),
'z': np.random.rand(100) * 100
})
(ggplot(df, aes(x='x', y='y', color='z'))
+ geom_point(size=8)
+ scale_color_gradient(low='blue', high='red')
+ guides(color=guide_colorbar(title='Value', barwidth=20)))
df = pd.DataFrame({
'x': np.random.rand(100),
'y': np.random.rand(100),
'z': np.random.rand(100) * 100
})
(ggplot(df, aes(x='x', y='y', color='z'))
+ geom_point(size=8)
+ scale_color_gradient(low='blue', high='red')
+ guides(color=guide_colorbar(title='Value', barwidth=20)))
Out[13]:
In [14]:
Copied!
df = pd.DataFrame({'x': range(1, 6), 'y': [2, 4, 3, 5, 4]})
(ggplot(df, aes(x='x', y='y'))
+ geom_line()
+ geom_point(size=10)
+ labs(
title='Main Title',
subtitle='This is a subtitle',
x='X-Axis Label',
y='Y-Axis Label',
caption='Data source: Example'
))
df = pd.DataFrame({'x': range(1, 6), 'y': [2, 4, 3, 5, 4]})
(ggplot(df, aes(x='x', y='y'))
+ geom_line()
+ geom_point(size=10)
+ labs(
title='Main Title',
subtitle='This is a subtitle',
x='X-Axis Label',
y='Y-Axis Label',
caption='Data source: Example'
))
Out[14]:
ggtitle()¶
Quick title addition:
In [15]:
Copied!
(ggplot(df, aes(x='x', y='y'))
+ geom_point(size=10)
+ ggtitle('Quick Title'))
(ggplot(df, aes(x='x', y='y'))
+ geom_point(size=10)
+ ggtitle('Quick Title'))
Out[15]:
In [16]:
Copied!
np.random.seed(42)
df = pd.DataFrame({
'x': np.random.randn(50),
'y': np.random.randn(50)
})
df.loc[50] = [3, 3] # Add outlier
(ggplot(df, aes(x='x', y='y'))
+ geom_point(size=6, alpha=0.6)
+ annotate('text', x=3, y=3.5, label='Outlier!', size=14, color='red')
+ annotate('rect', xmin=-1, xmax=1, ymin=-1, ymax=1, fill='lightblue', alpha=0.3)
+ annotate('text', x=0, y=0, label='Main cluster', size=12, color='blue'))
np.random.seed(42)
df = pd.DataFrame({
'x': np.random.randn(50),
'y': np.random.randn(50)
})
df.loc[50] = [3, 3] # Add outlier
(ggplot(df, aes(x='x', y='y'))
+ geom_point(size=6, alpha=0.6)
+ annotate('text', x=3, y=3.5, label='Outlier!', size=14, color='red')
+ annotate('rect', xmin=-1, xmax=1, ymin=-1, ymax=1, fill='lightblue', alpha=0.3)
+ annotate('text', x=0, y=0, label='Main cluster', size=12, color='blue'))
Out[16]:
Arrow Annotations¶
In [17]:
Copied!
df = pd.DataFrame({
'x': range(10),
'y': [1, 3, 2, 5, 8, 6, 4, 3, 2, 1]
})
(ggplot(df, aes(x='x', y='y'))
+ geom_line(size=2, color='steelblue')
+ geom_point(size=8)
+ annotate('segment', x=6, y=9, xend=4, yend=8.2, arrow=True, color='red', size=2)
+ annotate('text', x=6, y=9.5, label='Peak value', size=12, color='red'))
df = pd.DataFrame({
'x': range(10),
'y': [1, 3, 2, 5, 8, 6, 4, 3, 2, 1]
})
(ggplot(df, aes(x='x', y='y'))
+ geom_line(size=2, color='steelblue')
+ geom_point(size=8)
+ annotate('segment', x=6, y=9, xend=4, yend=8.2, arrow=True, color='red', size=2)
+ annotate('text', x=6, y=9.5, label='Peak value', size=12, color='red'))
Out[17]:
In [18]:
Copied!
(ggplot(df, aes(x='x', y='y'))
+ geom_line()
+ geom_point(size=10)
+ ggsize(width=1000, height=400)
+ labs(title='Wide Plot'))
(ggplot(df, aes(x='x', y='y'))
+ geom_line()
+ geom_point(size=10)
+ ggsize(width=1000, height=400)
+ labs(title='Wide Plot'))
Out[18]:
In [19]:
Copied!
gapminder = pd.DataFrame({
'year': [1952, 1962, 1972, 1982, 1992, 2002, 2007] * 2,
'lifeExp': [36.3, 40.0, 43.5, 48.1, 52.0, 52.7, 54.1,
68.4, 70.0, 71.0, 74.0, 77.0, 78.8, 78.2],
'country': ['Malawi'] * 7 + ['United States'] * 7
})
(ggplot(gapminder, aes(x='year', y='lifeExp', color='country'))
+ geom_line(size=3)
+ scale_x_continuous(format='d')
+ theme_bbc()
+ labs(title='Life Expectancy Over Time',
subtitle='Malawi vs United States'))
gapminder = pd.DataFrame({
'year': [1952, 1962, 1972, 1982, 1992, 2002, 2007] * 2,
'lifeExp': [36.3, 40.0, 43.5, 48.1, 52.0, 52.7, 54.1,
68.4, 70.0, 71.0, 74.0, 77.0, 78.8, 78.2],
'country': ['Malawi'] * 7 + ['United States'] * 7
})
(ggplot(gapminder, aes(x='year', y='lifeExp', color='country'))
+ geom_line(size=3)
+ scale_x_continuous(format='d')
+ theme_bbc()
+ labs(title='Life Expectancy Over Time',
subtitle='Malawi vs United States'))
Out[19]:
Minimal Academic Style¶
In [20]:
Copied!
df = pd.DataFrame({
'x': np.random.randn(100),
'y': np.random.randn(100)
})
(ggplot(df, aes(x='x', y='y'))
+ geom_point(size=6)
+ geom_smooth(method='lm', color='red')
+ theme_minimal()
+ theme(
axis_title=element_text(size=12),
plot_title=element_text(size=14)
)
+ labs(title='Scatter with Linear Fit',
x='Independent Variable',
y='Dependent Variable'))
df = pd.DataFrame({
'x': np.random.randn(100),
'y': np.random.randn(100)
})
(ggplot(df, aes(x='x', y='y'))
+ geom_point(size=6)
+ geom_smooth(method='lm', color='red')
+ theme_minimal()
+ theme(
axis_title=element_text(size=12),
plot_title=element_text(size=14)
)
+ labs(title='Scatter with Linear Fit',
x='Independent Variable',
y='Dependent Variable'))
Out[20]:
Dark Dashboard¶
In [21]:
Copied!
df = pd.DataFrame({
'x': np.random.randn(100),
'y': np.random.randn(100),
'group': np.random.choice(['A', 'B'], 100)
})
(ggplot(df, aes(x='x', y='y', color='group'))
+ geom_point(size=8)
+ theme_dark()
+ scale_color_manual(values=['#00ff00', '#ff00ff'])
+ labs(title='Dashboard Metric'))
df = pd.DataFrame({
'x': np.random.randn(100),
'y': np.random.randn(100),
'group': np.random.choice(['A', 'B'], 100)
})
(ggplot(df, aes(x='x', y='y', color='group'))
+ geom_point(size=8)
+ theme_dark()
+ scale_color_manual(values=['#00ff00', '#ff00ff'])
+ labs(title='Dashboard Metric'))
Out[21]:
In [22]:
Copied!
df = pd.DataFrame({
'x': np.tile(np.arange(10), 10),
'y': np.repeat(np.arange(10), 10),
'z': np.random.randn(100)
})
(ggplot(df, aes(x='x', y='y', fill='z'))
+ geom_tile()
+ scale_fill_gradient(low='blue', high='red')
+ theme_minimal()
+ labs(title='Heatmap with Custom Gradient'))
df = pd.DataFrame({
'x': np.tile(np.arange(10), 10),
'y': np.repeat(np.arange(10), 10),
'z': np.random.randn(100)
})
(ggplot(df, aes(x='x', y='y', fill='z'))
+ geom_tile()
+ scale_fill_gradient(low='blue', high='red')
+ theme_minimal()
+ labs(title='Heatmap with Custom Gradient'))
Out[22]:
Viridis for Accessibility¶
In [23]:
Copied!
(ggplot(df, aes(x='x', y='y', fill='z'))
+ geom_tile()
+ scale_fill_viridis_c()
+ theme_minimal()
+ labs(title='Colorblind-Friendly Heatmap'))
(ggplot(df, aes(x='x', y='y', fill='z'))
+ geom_tile()
+ scale_fill_viridis_c()
+ theme_minimal()
+ labs(title='Colorblind-Friendly Heatmap'))
Out[23]:
ColorBrewer Palettes¶
In [24]:
Copied!
df = pd.DataFrame({
'x': np.random.randn(150),
'y': np.random.randn(150),
'group': np.repeat(['A', 'B', 'C'], 50)
})
(ggplot(df, aes(x='x', y='y', color='group'))
+ geom_point(size=8)
+ scale_color_brewer(palette='Set2')
+ theme_minimal())
df = pd.DataFrame({
'x': np.random.randn(150),
'y': np.random.randn(150),
'group': np.repeat(['A', 'B', 'C'], 50)
})
(ggplot(df, aes(x='x', y='y', color='group'))
+ geom_point(size=8)
+ scale_color_brewer(palette='Set2')
+ theme_minimal())
Out[24]:
Theme Reference¶
| Theme Element | Description |
|---|---|
plot_background |
Overall plot background |
panel_background |
Panel (data area) background |
panel_grid_major |
Major gridlines |
panel_grid_minor |
Minor gridlines |
axis_line |
Axis lines |
axis_text |
Axis tick labels |
axis_title |
Axis titles |
axis_text_x |
X-axis tick labels only |
axis_text_y |
Y-axis tick labels only |
legend_position |
Legend placement |
legend_title |
Legend title text |
legend_text |
Legend item text |
plot_title |
Main title |
plot_subtitle |
Subtitle |
plot_caption |
Caption text |