我想将ggplot
个调用存储在data.frame
(或替代方法)中,并在以后进行评估。
一个例子:
define <- function(df, call) {
df[nrow(df) + 1, ] <- call
df
}
plot <- function(df, index) {
eval(parse(text = df$plots[index]))
}
df <- data.frame(plots = character(0), stringsAsFactors = FALSE)
df <- define(df, "ggplot() + geom_segment(aes(x = 1, y = 1, xend = 2, yend = 2))")
df <- define(df, "ggplot() + geom_segment(aes(x = 1, y = 2, xend = 2, yend = 1))")
plot(df, 1)
plot(df, 2)
这种作品和情节:
但是有一些问题:
define(df, ggplot() + geom_..)
。call
对象。我该如何实现?
答案 0 :(得分:4)
在这种情况下,我将使用一个列表。 data.frame
在存储未评估的内容时会有些棘手(因为它们包含的信息比调用还多)。列表更加通用(在这种情况下更易于使用):
#saves the unevaluated call
define <- function(mylist, call) {
mylist[[length(mylist) + 1]] <- substitute(call)
mylist
}
#evaluates the call
ploteval <- function(mylist, index) {
eval(mylist[[index]])
}
mylist <- list()
mylist <- define(mylist, ggplot() + geom_segment(aes(x = 1, y = 1, xend = 2, yend = 2)))
mylist <- define(mylist, ggplot() + geom_segment(aes(x = 1, y = 2, xend = 2, yend = 1)))
ploteval(mylist, 1)
ploteval(mylist, 2)
这将起作用。
作为一个简短的解释,替代将存储未评估的调用,然后将使用ploteval
对其进行评估。覆盖plot
也不是一个好主意,因此我给它起了一个新名称ploteval
。
答案 1 :(得分:2)
我们还可以将表达式捕获为表达式(enexpr
)并存储为字符串
define <- function(df, call) {
df[nrow(df) + 1, ] <- rlang::as_label(rlang::enexpr(call))
df
}
plot <- function(df, index) {
eval(parse(text = df[["plots"]][index]))
}
df <- data.frame(plots = character(0), stringsAsFactors = FALSE)
df <- define(df, ggplot() + geom_segment(aes(x = 1, y = 1, xend = 2, yend = 2)))
df <- define(df, ggplot() + geom_segment(aes(x = 1, y = 2, xend = 2, yend = 1)))
plot(df, 1)
plot(df, 2)