0
# Labels and Annotations
1
2
Labels and annotations enhance plot clarity and communication by adding titles, axis labels, legends, and descriptive text. Plotnine provides comprehensive labeling functions for all plot elements, supporting custom formatting, positioning, and styling to create publication-ready and presentation-quality visualizations.
3
4
## Capabilities
5
6
### Basic Labeling Functions
7
8
Core functions for setting plot titles, axis labels, and other text elements.
9
10
```python { .api }
11
def labs(**kwargs):
12
"""
13
Set labels for plot elements comprehensively.
14
15
Universal labeling function that can set any plot label including
16
titles, axis labels, legend titles, and caption text.
17
18
Parameters:
19
- title: str, main plot title
20
- subtitle: str, plot subtitle (appears below title)
21
- caption: str, plot caption (appears at bottom)
22
- x: str, x-axis label
23
- y: str, y-axis label
24
- color/colour: str, color legend title
25
- fill: str, fill legend title
26
- size: str, size legend title
27
- shape: str, shape legend title
28
- alpha: str, alpha legend title
29
- linetype: str, linetype legend title
30
- **kwargs: any other aesthetic legend titles
31
32
Usage: Preferred method for setting multiple labels at once
33
"""
34
35
def ggtitle(title, subtitle=None):
36
"""
37
Set plot title and optional subtitle.
38
39
Parameters:
40
- title: str, main plot title
41
- subtitle: str, optional subtitle text
42
43
Equivalent to labs(title=title, subtitle=subtitle)
44
"""
45
46
def xlab(label):
47
"""
48
Set x-axis label.
49
50
Parameters:
51
- label: str, x-axis label text
52
53
Equivalent to labs(x=label)
54
"""
55
56
def ylab(label):
57
"""
58
Set y-axis label.
59
60
Parameters:
61
- label: str, y-axis label text
62
63
Equivalent to labs(y=label)
64
"""
65
```
66
67
### Annotation Functions
68
69
Functions for adding text, shapes, and other annotations directly to plots.
70
71
```python { .api }
72
def annotate(geom, x=None, y=None, xmin=None, xmax=None, ymin=None, ymax=None,
73
xend=None, yend=None, **kwargs):
74
"""
75
Add annotations to plots using geometric objects.
76
77
Creates annotations without mapping to data variables, using fixed
78
coordinate positions and aesthetic values.
79
80
Parameters:
81
- geom: str, type of annotation ('point', 'text', 'segment', 'rect', etc.)
82
- x, y: float, position coordinates for point-like annotations
83
- xmin, xmax, ymin, ymax: float, rectangle bounds for 'rect' annotations
84
- xend, yend: float, end coordinates for 'segment' annotations
85
- **kwargs: aesthetic parameters (color, size, alpha, label, etc.)
86
87
Common geom types:
88
- 'text': text annotations
89
- 'point': point annotations
90
- 'segment': line segment annotations
91
- 'rect': rectangle annotations
92
- 'curve': curved line annotations
93
"""
94
95
def annotation_logticks(base=10, sides='bl', scaled=True, short=0.1, mid=0.2,
96
long=0.3, colour='black', size=0.5, linetype=1,
97
alpha=1, color=None, **kwargs):
98
"""
99
Add logarithmic tick marks to plots.
100
101
Adds small tick marks appropriate for logarithmic scales, with
102
different lengths for different orders of magnitude.
103
104
Parameters:
105
- base: float, logarithm base (usually 10)
106
- sides: str, which sides to add ticks ('t'=top, 'r'=right, 'b'=bottom, 'l'=left)
107
- scaled: bool, whether ticks should be scaled with plot
108
- short: float, length of short ticks (minor divisions)
109
- mid: float, length of medium ticks
110
- long: float, length of major ticks (powers of base)
111
- colour/color: str, tick color
112
- size: float, tick line width
113
- linetype: line type for ticks
114
- alpha: float, tick transparency
115
"""
116
117
def annotation_stripes(direction='horizontal', fill='grey90', colour='grey95',
118
alpha=1, color=None, **kwargs):
119
"""
120
Add background stripes to plots.
121
122
Creates alternating background stripes, useful for improving
123
readability of plots with many categories or time series.
124
125
Parameters:
126
- direction: str, stripe direction ('horizontal' or 'vertical')
127
- fill: str, stripe fill color
128
- colour/color: str, stripe border color
129
- alpha: float, stripe transparency
130
"""
131
```
132
133
## Usage Patterns
134
135
### Basic Plot Labeling
136
```python
137
# Comprehensive labeling with labs()
138
ggplot(data, aes(x='income', y='happiness', color='country')) + \
139
geom_point() + \
140
labs(
141
title='Income vs Happiness by Country',
142
subtitle='Data from World Happiness Report 2020',
143
caption='Source: World Happiness Report',
144
x='GDP Per Capita (USD)',
145
y='Happiness Score (0-10)',
146
color='Country'
147
)
148
149
# Individual labeling functions
150
ggplot(data, aes(x='x', y='y')) + \
151
geom_point() + \
152
ggtitle('My Scatter Plot', 'With a subtitle') + \
153
xlab('X Variable (units)') + \
154
ylab('Y Variable (units)')
155
```
156
157
### Legend Title Customization
158
```python
159
# Custom legend titles for different aesthetics
160
ggplot(data, aes(x='x', y='y', color='group', size='value', shape='category')) + \
161
geom_point() + \
162
labs(
163
color='Treatment\nGroup', # Use \n for line breaks
164
size='Measurement\nValue',
165
shape='Sample\nType'
166
)
167
168
# Remove legend titles
169
ggplot(data, aes(x='x', y='y', color='group')) + \
170
geom_point() + \
171
labs(color=None) # or labs(color='')
172
```
173
174
### Text Annotations
175
```python
176
# Basic text annotation
177
ggplot(data, aes(x='x', y='y')) + \
178
geom_point() + \
179
annotate('text', x=5, y=10, label='Important Point',
180
color='red', size=12, fontweight='bold')
181
182
# Multiple text annotations
183
ggplot(data, aes(x='year', y='value')) + \
184
geom_line() + \
185
annotate('text', x=2010, y=50, label='Economic Crisis',
186
hjust=0, vjust=0) + \
187
annotate('text', x=2015, y=75, label='Recovery Period',
188
hjust=0, vjust=0, color='blue')
189
190
# Text with background box (using geom_label style)
191
ggplot(data, aes(x='x', y='y')) + \
192
geom_point() + \
193
annotate('label', x=5, y=10, label='Highlighted',
194
fill='yellow', color='black', alpha=0.8)
195
```
196
197
### Shape and Line Annotations
198
```python
199
# Point annotations
200
ggplot(data, aes(x='x', y='y')) + \
201
geom_point() + \
202
annotate('point', x=5, y=10, color='red', size=5, shape='diamond')
203
204
# Line segment annotations
205
ggplot(data, aes(x='x', y='y')) + \
206
geom_point() + \
207
annotate('segment', x=2, y=5, xend=8, yend=15,
208
color='red', size=1.2, linetype='dashed')
209
210
# Rectangle annotations (highlighting regions)
211
ggplot(data, aes(x='date', y='value')) + \
212
geom_line() + \
213
annotate('rect', xmin=as.Date('2020-01-01'), xmax=as.Date('2020-06-01'),
214
ymin=-Inf, ymax=Inf, alpha=0.2, fill='red') + \
215
annotate('text', x=as.Date('2020-03-15'), y=50,
216
label='Lockdown Period', hjust=0.5)
217
```
218
219
### Mathematical and Scientific Notation
220
```python
221
# Mathematical expressions in labels
222
ggplot(data, aes(x='x', y='y')) + \
223
geom_point() + \
224
labs(
225
title='Population Growth Model',
226
x='Time (years)',
227
y='Population Size (N)',
228
subtitle=expression(N(t) == N[0] * e^{rt})
229
)
230
231
# Subscripts and superscripts in annotations
232
ggplot(chemistry_data, aes(x='pH', y='concentration')) + \
233
geom_point() + \
234
labs(
235
x='pH',
236
y=expression(paste('Concentration (mol L'^{-1}, ')'))
237
) + \
238
annotate('text', x=7, y=0.5,
239
label=expression(K[a] == 1.8 %*% 10^{-5}))
240
```
241
242
### Multi-line Labels and Formatting
243
```python
244
# Multi-line labels using \n
245
ggplot(data, aes(x='treatment', y='response')) + \
246
geom_boxplot() + \
247
labs(
248
title='Treatment Response Analysis',
249
subtitle='Comparison across\nmultiple treatment groups',
250
x='Treatment\nCondition',
251
y='Response\nMeasurement'
252
)
253
254
# Rich text formatting (when supported)
255
ggplot(data, aes(x='x', y='y')) + \
256
geom_point() + \
257
annotate('text', x=5, y=10,
258
label='*Important* **finding**',
259
hjust=0, parse=True)
260
```
261
262
### Conditional and Dynamic Annotations
263
```python
264
# Annotations based on data
265
max_point = data.loc[data['y'].idxmax()]
266
267
ggplot(data, aes(x='x', y='y')) + \
268
geom_point() + \
269
annotate('point', x=max_point['x'], y=max_point['y'],
270
color='red', size=4) + \
271
annotate('text', x=max_point['x'], y=max_point['y'],
272
label=f'Max: {max_point["y"]:.1f}',
273
hjust=-0.1, vjust=0.5, color='red')
274
275
# Multiple annotations in a loop
276
for i, row in important_points.iterrows():
277
plot += annotate('text', x=row['x'], y=row['y'],
278
label=row['label'], color='blue')
279
```
280
281
### Logarithmic Scale Annotations
282
```python
283
# Add log ticks to log-scaled plot
284
ggplot(data, aes(x='dose', y='response')) + \
285
geom_point() + \
286
scale_x_log10() + \
287
scale_y_log10() + \
288
annotation_logticks(sides='bl') + \
289
labs(
290
x='Dose (log scale)',
291
y='Response (log scale)'
292
)
293
```
294
295
### Background Stripes and Highlighting
296
```python
297
# Horizontal stripes for categorical data
298
ggplot(data, aes(x='value', y='category')) + \
299
annotation_stripes(direction='horizontal') + \
300
geom_point(size=3) + \
301
theme_minimal()
302
303
# Vertical stripes for time series
304
ggplot(time_data, aes(x='date', y='value')) + \
305
annotation_stripes(direction='vertical', alpha=0.1) + \
306
geom_line(size=1) + \
307
theme_minimal()
308
```
309
310
### Advanced Annotation Techniques
311
```python
312
# Curved annotations (arrows)
313
ggplot(data, aes(x='x', y='y')) + \
314
geom_point() + \
315
annotate('curve', x=2, y=3, xend=5, yend=8,
316
curvature=0.3, arrow=arrow(type='closed', length=unit(0.1, 'inches')),
317
color='red', size=1) + \
318
annotate('text', x=2, y=2.5, label='Trend direction', color='red')
319
320
# Combine multiple annotation types
321
ggplot(data, aes(x='year', y='gdp')) + \
322
geom_line(size=1) + \
323
# Highlight recession period
324
annotate('rect', xmin=2008, xmax=2009, ymin=-Inf, ymax=Inf,
325
alpha=0.2, fill='red') + \
326
# Add recession label
327
annotate('text', x=2008.5, y=max(data['gdp']) * 0.9,
328
label='Financial Crisis', hjust=0.5, color='red', fontweight='bold') + \
329
# Mark specific data point
330
annotate('point', x=2008, y=data.query('year == 2008')['gdp'].iloc[0],
331
color='red', size=4) + \
332
labs(
333
title='GDP Over Time',
334
subtitle='Highlighting the 2008 Financial Crisis',
335
x='Year',
336
y='GDP (Trillions USD)'
337
)
338
```
339
340
### Positioning and Alignment
341
```python
342
# Control text alignment with hjust and vjust
343
ggplot(data, aes(x='x', y='y')) + \
344
geom_point() + \
345
# Left-aligned text
346
annotate('text', x=5, y=10, label='Left', hjust=0, vjust=0.5) + \
347
# Center-aligned text
348
annotate('text', x=5, y=8, label='Center', hjust=0.5, vjust=0.5) + \
349
# Right-aligned text
350
annotate('text', x=5, y=6, label='Right', hjust=1, vjust=0.5)
351
352
# Rotate text annotations
353
ggplot(data, aes(x='x', y='y')) + \
354
geom_point() + \
355
annotate('text', x=5, y=10, label='Rotated Text',
356
angle=45, hjust=0.5, vjust=0.5)
357
```
358
359
### Theme Integration with Labels
360
```python
361
# Ensure labels work well with theme
362
ggplot(data, aes(x='x', y='y', color='group')) + \
363
geom_point() + \
364
labs(
365
title='My Analysis',
366
subtitle='Important findings',
367
x='Predictor Variable',
368
y='Response Variable',
369
color='Group',
370
caption='Data source: My dataset'
371
) + \
372
theme_minimal() + \
373
theme(
374
plot_title=element_text(size=16, hjust=0.5),
375
plot_subtitle=element_text(size=12, hjust=0.5, color='gray50'),
376
plot_caption=element_text(size=8, hjust=1, color='gray50'),
377
axis_title=element_text(size=11),
378
legend_title=element_text(size=10)
379
)
380
```