ggplot2
ggplot2 copied to clipboard
[Feature request] Let `element_text()` change text values
This would allow a user to supply a function to element_text()
which would be applied to the text itself.
Hear me out. Often, to make plots slightly prettier, labels are transformed from data values (e.g. Sepal.Length
, setosa
) to more human-readable versions (e.g. Sepal Length
, Setosa
). This often follows a few simple rules, e.g. spaces instead of underscores, appropriate capitalisation etc. Currently there's two main ways to do achieve this:
- Use
labs()
if variable names are the problem. This isn't easy to do programmatically and can be annoying, especially if you just want to do something simple like switch underscores for spaces - Pre-format the data (e.g. using
dplyr::mutate()
) if data values are the problem. I think this is slightly easier, but is still not ideal.
I think being able to do this in one step via element_text()
, perhaps via a transform
argument, would be really nice - although it feels like it would somewhat break with the pattern of element_
functions only changing formatting. Here's an example of how it might be used:
library(dplyr, warn.conflicts = FALSE)
library(stringr)
# Without `transform` argument:
iris |>
mutate(Species = stringr::str_to_title(Species)) |>
ggplot(aes(Sepal.Length, Sepal.Width, colour = Species)) +
geom_point() +
labs(
x = "Sepal Length",
y = "Sepal Width"
)
# With `transform` argument:
ggplot(iris, aes(Sepal.Length, Sepal.Width, colour = Species)) +
geom_point() +
theme(
text = element_text(
transform = \(x) x |> str_replace_all("\\.", " ") |> str_to_title()
)
)
This would also be really nice for defining custom theme_
functions.
Possibly something that should just have its own package, but my view is that it would be useful and general enough to justify inclusion in ggplot2 itself.
It is not too difficult to just build this on top of element_text()
if you want.
library(ggplot2)
library(stringr)
element_text_transform <- function(..., transform = identity) {
elem <- element_text(...)
elem$transform <- rlang::as_function(transform)
class(elem) <- c("element_text_transform", class(elem))
elem
}
element_grob.element_text_transform <- function(element, label = "", ...) {
label <- element$transform(label)
NextMethod()
}
ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species)) +
geom_point() +
theme(
legend.text = element_text_transform(
transform = ~ str_replace_all(.x, "\\.", " ") |> str_to_title()
)
)
Created on 2022-08-14 by the reprex package (v2.0.1)
It is not too difficult to just build this on top of
element_text()
if you want.library(ggplot2) library(stringr) element_text_transform <- function(..., transform = identity) { elem <- element_text(...) elem$transform <- rlang::as_function(transform) class(elem) <- c("element_text_transform", class(elem)) elem } element_grob.element_text_transform <- function(element, label = "", ...) { label <- element$transform(label) NextMethod() } ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species)) + geom_point() + theme( legend.text = element_text_transform( transform = ~ str_replace_all(.x, "\\.", " ") |> str_to_title() ) )
Created on 2022-08-14 by the reprex package (v2.0.1)
Very nice! This does require some knowledge of {ggplot2}’s inner workings though. But nice to know it can be done so simply :)
Hi Jacob, giving this issue some thoughts more recently; I think this feature might better fit an extension package rather than ggplot2 itself. The example I gave earlier should be a reasonable template for implementing an element_text()
extension.
Even though it is unlikely to be implemented in ggplot2, I would like to thank you for suggesting the feature and hope you reach out again if you have other ideas for features.
This is a very useful trick! A quirk of this method is that it seems to only work for concrete fields like legend.text
or axis.title.x
, not for abstract fields like axis.title
.
I would also put in an argument to reconsider adding this feature to the standard interface. As is, you have to manually specify labels for them to look good, and this is what most programmer do in my experience. Sure, this takes some time. But the much larger problem is that you can change what is being plotted and forget to change the labels. This can easily lead to creating incorrectly labeled plots, which is of course a serious problem. Having an easy way to automatically reformat variable names would avoid this situation.