如何通过列表中的项目名称保存图

时间:2019-03-21 20:54:25

标签: r plot lapply glm

我可以保存一堆图,但是它将其命名为每个列表项的第一个值,而不是变量的名称。

delm2<-data.frame(N = c(5.881, 5.671, 7.628, 4.643, 6.598, 4.485, 4.465, 4.978, 4.698, 3.685, 4.915, 4.983, 3.288, 5.455, 5.411, 2.585, 4.321, 4.661), 
                  t1 = c("N", "N", "T", "T", "N", "N", "T", "N", "N", "N", "N", "T", "T", "T", "T", "T", "T", "N"), 
                  t3 = c("r","v", "r", "v", "v", "r", "c", "c", "v", "r", "c", "c", "r", "v","c", "r", "v", "c"), 
                  B = c(1.3, 1.3, 1.33, 1.25, 1.4, 1.34, 1.36, 1.39, 1.36, 1.42, 1.38, 1.31, 1.37, 1.44, 1.22, 1.4, 1.46, 1.35))


library(boot)

lapply(as.list(delm2[,c('N','B')]), 
       function(i){
         bmp(filename = paste0(i,".bmp"), width = 350, height = 400)
         glm.diag.plots(glm(i ~ t1*t3,data=del))
         dev.off()   
       })

这将保存图,但是它们使用来自数据的数字值而不是lapply的每个目标的名称来命名... 即当前的输出是两个名为“ 5.881”和“ 1.3”的文件,当我想要相同的两个文件但名为“ N”和“ B”的

我以为我可以将paste0(i,".bmp")更改为paste0(names(i),".bmp"),但这只会保存第一个,而根本没有名称。

看起来您可以在How to save and name multiple plots with R中提供只是整数的名称,但我希望从列表中获得变量的名称,或者在delm2中获得两个数字NB。 / p>

Saving a list of plots by their names()看来,使用ggplot输出会更容易,但是ggsave不能用于一个glm.diag.plots输出。

1 个答案:

答案 0 :(得分:1)

(忽略我先前使用Map的建议。)

最大的收获是如何动态推导公式。一种方法是使用as.formula,该方法接受一个字符串并将其转换为可在模型生成函数中使用的公式(例如)。

使用lapply(as.list(delm2[,c('N','B')]), ...)的一个问题是,其余数据(即列t1t3)没有传递,一次仅传递了一个向量。 (我想知道您对del的引用是否是错字,未发布/隐藏的数据或其他。)

尝试一下:

lapply(c("N", "B"), function(nm) {
  bmp(filename = paste(nm, ".bmp"), width = 350, height = 400)
  glm.diag.plots(glm(as.formula(paste(nm, "~ t1*t3")), data = delm2))
  dev.off()
})

通常,我不喜欢在这些函数中违反范围。也就是说,当我可以很容易地传递数据时,我尝试不到达lapply之外。上面的一种古怪的语言看起来像:

lapply(c("N", "B"), function(nm, x) {
  bmp(filename = paste(nm, ".bmp"), width = 350, height = 400)
  glm.diag.plots(glm(as.formula(paste(nm, "~ t1*t3")), data = x))
  dev.off()
}, x = delm2)

虽然这保留了作用域,但如果您不了解正在发生的事情,可能会造成混淆。

这可能是使用for而不是*apply*函数之一的好时机。您想要的一切都是副作用,并且由于for*apply的速度实际上是相同的,因此您可以获得可读性:

for (nm in c("N", "B")) {
  bmp(filename = paste(nm, ".bmp"), width = 350, height = 400)
  glm.diag.plots(glm(as.formula(paste(nm, "~ t1*t3")), data = delm2))
  dev.off()
}

(在这种情况下,没有“范围违反”,因此我使用了原始变量。)


从精神上,以配合我现在编辑的错误答案,其中包括Map。这是一个使用Map的示例,它可以进一步证明Map(和mapply)在做什么,反而实际上可以改善您的迫切需求。

如果出于某些原因您希望他们命名与"N.bmp"不同的名称,则可以执行以下操作:

Map(function(fn, vn, x) {
  bmp(filename = paste(nm, ".bmp"), width = 350, height = 400)
  glm.diag.plots(glm(as.formula(paste(nm, "~ t1*t3")), data = x))
  dev.off()
}, c("N2.bmp", "b3456.bmp"), c("N", "B"), list(delm2))

需要注意的两件事:

  • list(delm2)的使用是将该结构包装为单个“事物”,然后将其重复传递给映射函数。如果我们只做delm2(不做list(...)),那么它将尝试将delm2的第一列与每个第一元素一起使用。这在其他情况下可能很有用,但是在您的glm示例中,您需要显示其他列,因此您一次不能仅包含一列。 (嗯,也有办法做到这一点,但是目前很重要。)
  • 第一次调用匿名函数时,fn"N2.bmp",vn is“ N” , and x is the full dataset of delm2 . The second time the anon-func is called, fn is“ b3456.bmp” , vn is“ B” , and x is again the full dataset of delm2`。

我将此部分标记为“括号”,因为它实际上并没有添加到这个问题中,但是由于我是从第一答案中开始的,所以我认为我会继续使用该方法,我选择Map的“为什么”。最后,我认为for解决方案或lapply解决方案之一适合您。