plotly drops the size legend when marker size encodes a numeric column
(plotly.R#705), whether the figure comes from plotly::ggplotly() or is
built by hand. This draws one in its place: a vertical column of circles
with numeric labels, outside the right edge of the plot area in
paper-referenced coordinates so it does not overlap the data. The breaks run
evenly across the size scale's limits, and each circle is drawn at the size
the scale gives its value, so the legend follows the plot's size scaling. The
DotPlot and scatter plot modules use it, and a module in another package can
too.
Usage
add_size_legend(
fig,
data,
size.by,
gap = 0.05,
size.values = NULL,
title = size.by,
digits = NULL,
title.size = NULL,
text.size = NULL,
start.y = 0.95,
start.x = 1.02,
font.family = NULL,
font.color = NULL,
limits = NULL,
size.range = NULL,
breaks = NULL
)Arguments
- fig
A plotly figure object.
- data
A data frame containing the variable mapped to point size.
- size.by
Character string, or
NULL. Name of the column indatawhose range determines the legend break labels. WhenNULLor empty (no size mapping is in effect), the figure is returned unchanged.- gap
Numeric. Vertical spacing (in paper units, 0–1) between consecutive legend entries. Defaults to
0.05.- size.values
Numeric vector of font sizes (px) used to render the circle glyphs, one per legend entry. When
NULL(the default), the glyph sizes follow the plot's size scaling: fromsize.rangewhen it is given, otherwise from the marker sizes infig. The marker pixel diameters are converted to glyph font-sizes via.CIRCLE_GLYPH_DIAMETER_RATIOso the rendered circles match the plotted dots. When supplied, the vector is used verbatim as font sizes and its length determines the number of legend entries.- title
Character. Legend title. Defaults to
size.by.- digits
Integer, or
NULL. Decimal places the break labels are rounded to. WhenNULL(the default), the break values are printed as they are.- title.size
Numeric, or
NULL. Font size (px) of the legend title annotation. WhenNULL, plotly's default is used.- text.size
Numeric, or
NULL. Font size (px) of the numeric label annotations. Defaults to12whenNULL.- start.y
Numeric. Paper-space y coordinate (0–1) at which the legend column begins; the title sits just above it and subsequent entries stack downward. Lower it to vertically offset the size legend from an overlapping color/shape legend. Invalid values fall back to the default. Defaults to
0.95.- start.x
Numeric. Paper-space x coordinate at which the legend column (circles, labels and title) is anchored. Values just above
1place the legend to the right of the plot area; nudge it lower to pull the whole set inward when it would otherwise overflow a narrow plot, or higher to push it further out. Defaults to1.02.- font.family
Character, or
NULL. Font family of the title and label annotations. WhenNULL, plotly's default is used.- font.color
Character, or
NULL. Font color of the title and label annotations. Defaults to"#000000"whenNULL. The circles stay black.- limits
Numeric length-2 vector, or
NULL. Thesize.byvalues drawn at the smallest and largest sizes, as given to the plot's size scale. The breaks run evenly between them. ANAend takes the data's minimum or maximum, and limits that are not in increasing order fall back to the data's range. Defaults toNULL, the data's range.- size.range
Numeric length-2 vector, or
NULL. The size range the plot's size scale mapslimitsonto, in ggplot2 size units (therangeofggplot2::scale_size()). When given, each circle is drawn at the size the scale gives its break. WhenNULL(the default), the circles are read from the marker sizes infig.- breaks
Numeric vector, or
NULL. Thesize.byvalues to draw a circle for, in place of five spaced evenly between the limits. Values outside the limits are dropped. Useful for round labels, or to leave out the lower limit of a scale whosesize.rangestarts at 0, which would draw an empty circle. Whensize.valuesis also given, it is recycled to one glyph size per break. Defaults toNULL.
Value
The built plotly figure with size-legend annotations appended, or
the unmodified figure when size.by is NULL/empty, not present in
data, not numeric, or has no finite values.
Details
For a ggplot drawn with scale_size(range = r, limits = l), pass
size.range = r and limits = l. Without size.range, the circles are read
from the figure's own markers instead, taking its smallest and largest to be
the data's minimum and maximum.
Call it after the figure's traces are complete. It builds the figure and
appends its annotations to the built layout, so later
plotly::plotly_build() calls (e.g. apply_legend_inputs() or
axis_titles_as_annotations()) do not duplicate them. A module hiding its
legend should pass size.by = NULL.
Examples
library(plotly)
df <- data.frame(x = 1:5, y = c(2, 4, 3, 5, 1), n = c(10, 40, 25, 80, 55))
fig <- plot_ly(df, x = ~x, y = ~y, type = "scatter", mode = "markers",
marker = list(size = sqrt(df$n) * 3))
add_size_legend(fig, df, size.by = "n", title = "Count", digits = 0)
# A ggplot with a fixed size scale: the legend runs 0, 25, ..., 100.
library(ggplot2)
p <- ggplot(df, aes(x, y, size = n)) +
geom_point() +
scale_size(range = c(2, 8), limits = c(0, 100))
add_size_legend(ggplotly(p), df, size.by = "n", limits = c(0, 100), size.range = c(2, 8))