21.3 Part 2: Adding aesthetics
We’ll tackle the first challenge by turning the diameter
and tension
arguments into aesthetics that can be set per-spring.
There is surprisingly little to do here:
ggproto("StatSpring", Stat,
StatSpring <-setup_data = function(data, params) {
if (anyDuplicated(data$group)) {
$group <- paste(data$group, seq_len(nrow(data)), sep = "-")
data
}
data
},compute_panel = function(data, scales, n = 50) {
setdiff(names(data), c("x", "y", "xend", "yend"))
cols_to_keep <- lapply(seq_len(nrow(data)), function(i) {
springs <- create_spring(data$x[i], data$y[i], data$xend[i],
spring_path <-$yend[i], data$diameter[i],
data$tension[i], n)
datacbind(spring_path, unclass(data[i, cols_to_keep]))
})do.call(rbind, springs)
},required_aes = c("x", "y", "xend", "yend"),
optional_aes = c("diameter", "tension")
)
The main difference with our previous attempt is that the diameter
and tension
arguments to compute_panel()
have gone away, and they’re now taken from the data (just like x
, y
, etc).
This has a downside (that we’ll fix shortly): we can no longer set fixed aesthetics so we’ll also need to remove from the constructor:
function(mapping = NULL, data = NULL, stat = "spring",
geom_spring <-position = "identity", ..., n = 50, arrow = NULL,
lineend = "butt", linejoin = "round", na.rm = FALSE,
show.legend = NA, inherit.aes = TRUE) {
layer(
data = data,
mapping = mapping,
stat = stat,
geom = GeomPath,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
n = n,
arrow = arrow,
lineend = lineend,
linejoin = linejoin,
na.rm = na.rm,
...
)
) }
The stat_spring()
constructor would require the same kind of change.
All that is left is to test our new implementation out:
tibble(
some_data <-x = runif(5, max = 10),
y = runif(5, max = 10),
xend = runif(5, max = 10),
yend = runif(5, max = 10),
class = sample(letters[1:2], 5, replace = TRUE),
tension = runif(5),
diameter = runif(5, 0.5, 1.5)
)
ggplot(some_data, aes(x, y, xend = xend, yend = yend)) +
geom_spring(aes(tension = tension, diameter = diameter))
It appears to work, we can no longer set diameter
and tension
as parameters:
ggplot(some_data, aes(x, y, xend = xend, yend = yend)) +
geom_spring(diameter = 0.5)
#> Warning: Ignoring unknown parameters: diameter
#> Warning: Computation failed in `stat_spring()`:
#> argument is of length zero
21.3.1 Post-Mortem
In this section we further developed our spring stat so that diameter
and tension
can be used as aesthetics, varying across springs.
Unfortunately, there’s a major downside: these features no longer can be set globally.
We’re still also missing a way to control the scaling of the two aesthetics.
Fixing both these problems requires the same next step: move our implementation away from Stat
and towards a proper Geom
.