我编写了一个函数来制作散点图,该函数允许用户将点的大小输入为数值(保留在 aes()
调用之外)或作为要映射的数据帧中的变量(需要进入 aes() 调用内部)。我远不是 NSE 方面的专家,尽管我已经让它发挥作用,但我觉得必须有更好的方法来做到这一点?
该函数的简化版本如下:
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)
由reprex package于2021年4月8日创建(v2.0.0)
最佳答案
一个选项是检查用户提供给变量
的内容是否是数据
中的列。如果是,请在 aes()
映射中使用该列。如果不是,则评估变量并将结果提供给 aes()
之外的 size
:
test_func <- function(data, variable = 6) {
v <- enquo(variable)
gg <- ggplot(data, aes(x=x, y=y))
if(exists(rlang::quo_text(v), data))
gg + geom_point(aes(size=!!v))
else
gg + geom_point(size = rlang::eval_tidy(v))
}
# All of these work as expected:
test_func(data) # Small points
test_func(data, 10) # Bigger points
test_func(data, x) # Using column x
作为奖励,此解决方案允许您传递存储在变量中的值,而不是直接数字输入。只要变量名称不在 data
中,它就会被正确计算并馈送到 size=
:
z <- 20
test_func(data, z) # Works
关于r - ggplot2 函数 - 检查用户输入变量是否应该是映射的美学,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67007646/