在R中使用for循环和ggplot处理承诺(rlang)

在R中使用for循环和ggplot处理承诺(rlang),r,ggplot2,rlang,R,Ggplot2,Rlang,此脚本的目的是复制类似下图的内容: 可在以下网址找到: 我遇到的问题与(我认为)R如何处理我在ggplot中的承诺有关 下面的例子再现了我的问题 library(tidyverse) process_starting_row <- 600 per_validation_period <- 30 number_of_validations <- 5 graphical_data <- data.frame(x= 1:(process_starting_row + 1 +

此脚本的目的是复制类似下图的内容: 可在以下网址找到:

我遇到的问题与(我认为)R如何处理我在ggplot中的承诺有关

下面的例子再现了我的问题

library(tidyverse)
process_starting_row  <- 600
per_validation_period <- 30
number_of_validations <- 5

graphical_data <- data.frame(x= 1:(process_starting_row + 1 + (number_of_validations)*per_validation_period))

for (it in 1:number_of_validations) {

  # For this graph there is always a line and then a colour component explaining each one...
  graphical_data[,paste0("iteration",it,"line")]   <- c(it)

  # First make the whole row grey and then "dolly up" the colours.
  graphical_data[,paste0("iteration",it,"colour")] <- "grey"
  graphical_data[1:(process_starting_row + (it-1)*per_validation_period), paste0("iteration",it,"colour")] <- "blue"
  graphical_data[(process_starting_row + 1 + (it)*per_validation_period), paste0("iteration",it,"colour")] <- "red"

}
#graphical_data
我希望迭代的就是这个基本对象

我编写了一个函数,它将添加每个迭代
gg_adding()
,然后再添加另一个
ggaddfor()
,运行for循环

gg_adding <- function(data, iteration_sub, color_sub){
  iteration_promise <- enquo(iteration_sub)
  colour_promise <- enquo(color_sub)
  gg  <- geom_point(data = data, aes(x= x, y= !! iteration_promise, color = !! colour_promise))
  return(gg)
}

ggaddfor <- function(data, gg){
  ggout <- gg
for (it in 1:number_of_validations) {
  #print(it)
  iterationsub <- paste0("iteration",it,"line")
  coloursub <- paste0("iteration",it,"colour")

  ggout <- ggout + gg_adding(data, iterationsub, coloursub)

  }
  return(ggout)
}
它生成的输出如下所示:

显然这不是我所希望的。。。 为了测试,我明确规定了每次迭代

    # Working...
ggadd <- ggbase
ggadd <- ggadd + gg_adding(graphical_data, iteration1line, iteration1colour)
ggadd <- ggadd + gg_adding(graphical_data, iteration2line, iteration2colour)
ggadd <- ggadd + gg_adding(graphical_data, iteration3line, iteration3colour)
ggadd <- ggadd + gg_adding(graphical_data, iteration4line, iteration4colour)
ggadd <- ggadd + gg_adding(graphical_data, iteration5line, iteration5colour)
#正在工作。。。

ggadd对我有效的方法是将
gg\u adding()
函数中的
enquo()
调用替换为
as.symbol()
,这样新函数将如下所示:

gg_adding <- function(data, iteration_sub, color_sub){
  iteration_promise <- as.symbol(iteration_sub)
  colour_promise <- as.symbol(color_sub)
  gg  <- geom_point(data = data, aes(x= x, y= !! iteration_promise, color = !! colour_promise))
  return(gg)
}
我对整洁的评估和报价略知一二,但并不完全熟悉。我理解的是,无论您在
aes()
中输入什么,都将在
data
列名的上下文中进行计算,首先在层的数据中,然后在全局数据中,除非用户在其调用中是显式的(例如
aes(fill=“black”)
或其他内容)。由于
ggbase
构造中已经指定了
x
data
的值,因此在
geom_point()
调用中不需要它

gg  <- geom_point(aes(y= !! iteration_promise, color = !! colour_promise))
我知道这可能是一个不请自来的提示,我很抱歉,但ggplot似乎更喜欢使用长数据而不是宽数据。我对“宽”数据的意思是,您的迭代有点像
cbind()
-ed。因此,如果您首先计算每个迭代,然后将它们一起计算,
rbind()

new_gr_dat <- lapply(seq_len(number_of_validations), function(it){
  df <- data.frame(x= 1:(process_starting_row + 1 + (number_of_validations)*per_validation_period),
                   line = it, # doubles as y-value and iteration tracker
                   colour = "grey")
  df[1:(process_starting_row + (it-1)*per_validation_period), "colour"] <- "blue"
  df[(process_starting_row + 1 + (it)*per_validation_period), "colour"] <- "red"
  return(df)
})
new_gr_dat <- do.call(rbind, new_gr_dat)

ggplot(new_gr_dat, aes(x = x, y = line, colour = colour)) +
  geom_point() +
  coord_cartesian(xlim = c(process_starting_row-1*per_validation_period, max(new_gr_dat$x)))

new\u gr\u dat看起来您正在向参数传递字符串,例如
ggadding()
中的
iterationsub
。在这种情况下,一个选项是在
ggadding()
函数中将
enquo()
替换为
sym()
。在您的测试用例中,您将参数作为符号而不是字符串进行传递,这就是为什么
ggadding()
在这里可以正常工作的原因。@aosmith谢谢!这就解决了问题。这也使两者之间的区别更加明确。我感谢你的帮助。
gg  <- geom_point(aes(y= !! iteration_promise, color = !! colour_promise))
new_gr_dat <- lapply(seq_len(number_of_validations), function(it){
  df <- data.frame(x= 1:(process_starting_row + 1 + (number_of_validations)*per_validation_period),
                   line = it, # doubles as y-value and iteration tracker
                   colour = "grey")
  df[1:(process_starting_row + (it-1)*per_validation_period), "colour"] <- "blue"
  df[(process_starting_row + 1 + (it)*per_validation_period), "colour"] <- "red"
  return(df)
})
new_gr_dat <- do.call(rbind, new_gr_dat)

ggplot(new_gr_dat, aes(x = x, y = line, colour = colour)) +
  geom_point() +
  coord_cartesian(xlim = c(process_starting_row-1*per_validation_period, max(new_gr_dat$x)))