【问题标题】:Using "eval" within a loop在循环中使用“eval”
【发布时间】:2025-12-04 03:30:01
【问题描述】:

我想动态地将绘图分配给变量名称,然后在循环中调用该变量。虽然在循环外使用“eval”似乎工作得很好,但将它放在循环中会阻止它按预期工作。

#Sample data frame
x<-c(1,2,3,4,5)
y<-c(5,4,3,2,1)
y2<-c(1,2,3,4,5)


DF<-data.frame(x,y,y2)


#Using ggplot for p and p2
p<-ggplot(DF, aes(x=x, y=y))+
            geom_point()
p2<-ggplot(DF, aes(x=x, y=y2))+
  geom_point()

#Assign p and p2 to string "Plot1" and "Plot2"
assign(paste0("Plot",1), p )
assign(paste0("Plot",2), p2 )


#Create a list to hold all plot names
plotlist<-c("Plot1", "Plot2")




#Print plots to a pdf
pdf(paste0("Plot", "_Test.pdf"), height =8, width=16)

for(i in seq(1,length(plotlist))){
  plotname<-plotlist[i]
  plotter<-eval(parse(text=plotname))
  plotter
  print(plotname)

}

dev.off()

请注意,上述方法不起作用。但是,如果我要在循环之外运行相同的 eval 语句,AKA:

  i=1
  plotname<-plotlist[i]
  plotter<-eval(parse(text=plotname))
  plotter

情节按预期创建。有没有办法在循环中调用“eval”?如果处于循环中会导致 eval 语句的工作方式不同呢?

注意,通过删除 for 循环,它会按预期保存(第一个)pdf:

pdf(paste0("Plot", "_Test.pdf"), height =8, width=16)

#for(i in seq(1,length(plotlist))){
  plotname<-plotlist[i]
  plotter<-eval(parse(text=plotname))
  plotter
  print(plotname)

#}

dev.off()

【问题讨论】:

  • 应该是print(plotter),而不是print(plotname),将绘图实际打印到输出设备,而不仅仅是名称(或者您可以同时打印两者)。但是在 R 中使用 assigneval 并不是一个好的模式。您应该将相关项目存储在列表中并在这些列表上应用函数而不是循环。它让一切变得如此简单。
  • “print”语句是为了打印出“plotname”以确保我正在评估正确的语句
  • 绘图应从打印语句上方的“绘图仪”行打印
  • 嗯,你需要在循环内显式地print() ggplot 对象,否则它们不会像基本图形图那样渲染。例如,请参阅*.com/questions/15678261/…
  • 如果我在 print(plotname) 之前添加 print(plotter) 并运行你的第一个代码块,我会得到一个包含两个图的 pdf。您还有其他问题要解决吗?

标签: r for-loop eval assign


【解决方案1】:

避免分配/评估的更类似于 R 的方法是

DF <- data.frame(
  x = c(1,2,3,4,5),
  y = c(5,4,3,2,1),
  y2 = c(1,2,3,4,5))

plotlist <- list(
  Plot1 = ggplot(DF, aes(x=x, y=y)) +
    geom_point(),  
  Plot2 = ggplot(DF, aes(x=x, y=y2)) +
    geom_point()
)

pdf(paste0("Plot", "_Test.pdf"), height =8, width=16)
lapply(plotlist, print)
dev.off()

您在此处的所有图都可以轻松存储在一个列表中,我们可以在需要时通过lapply() 完成。

主要问题是 ggplot 对象在 print()ed 之前不会渲染。在控制台中工作时,默认情况下最后一个表达式的结果是print()ed。但是当你运行一个循环时,默认的print()ing 不会发生。这在上一个问题中有所描述:R: ggplot does not work if it is inside a for loop although it works outside of it

【讨论】: