I've written a function to make a scatter plot that allows the user to input the size of the points as either a numeric value (which is kept outside the aes()
call) or as a variable in the data frame to be mapped (which needs to go inside the aes()
call). I'm far from an expert in NSE and, although I've got it working, I feel like there must be a better way to do this?
A simplified version of the function is as follows:
library(tidyverse)
data <- tibble(x = 1:10, y = 1:10)
test_func <- function(data, variable = 6){
# capture the variable in vars (I think quote would also work in this function)
variable <- vars({{variable}})
# convert it to a string and check if the string starts with a digit
# i.e. checking if this is a simple point size declaration not an aes mapping
is_number <- variable[[1]] %>%
rlang::as_label() %>%
str_detect("^[:digit:]*$")
# make initial ggplot object
p <- ggplot(data, aes(x = x, y = y))
# if variable is a simple number, add geom_point with no aes mapping
if(is_number){
variable <- variable[[1]] %>%
rlang::as_label() %>%
as.numeric()
p <- p + geom_point(size = variable)
} else{
# otherwise it must be intended as an aes mapping variable
variable <- variable[[1]] %>%
rlang::as_label()
p <- p + geom_point(aes(size = .data[[variable]]))
}
p
}
# works as a number
test_func(data, 10)
# works as a variable
test_func(data, y)
Created on 2021-04-08 by the reprex package (v2.0.0)