了解如何读取设备列表

Jor*_*eys 3 graphics r device

我在开放设备列表中遇到了一个相当恼人的问题,试图构建一个为列表保存大量图形的函数.假设我们有以下数据:

Alist <- list(
  X1 = data.frame(X=rnorm(10),Y=1:10),
  X2 = data.frame(X=rnorm(10),Y=1:10),
  X3 = data.frame(X=rnorm(10),Y=1:10)
)
Run Code Online (Sandbox Code Playgroud)

和以下功能:

myPlotFunc <- function(x,save=F){
    fnames <- paste(names(x),"pdf",sep=".")
    for(i in 1:length(x)){
      if(save){
        pdf(fnames[i])
        on.exit(dev.off(),add=T)
      }
      plot(x[[i]])
    }
    fnames
  }
Run Code Online (Sandbox Code Playgroud)

如果我跑fnames <- myPlotFunc(Alist,save=T),一切都可以正常工作,我得到3 PDF文件名X1.pdfX3.pdf.也就是说,如果没有图形窗口打开.如果有,则其中一个pdf未关闭,所有后续绘图都添加到pdf,直到我dev.off()在控制台中显式调用.像这样 :

plot(Alist[[1]])
fnames <- myPlotFunc(Alist,save=T)
myPlotFunc(Alist,save=F)

> dev.list()
pdf 
  4 
Run Code Online (Sandbox Code Playgroud)

如果我添加on.exit({print(dev.cur());dev.off()},add=T),我得到以下输出:

> fnames <- myPlotFunc(Alist,save=T)
pdf 
  5 
windows 
      2 
pdf 
  3 
Run Code Online (Sandbox Code Playgroud)

所以显然它需要自下而上的列表来关闭它遇到的一切.因此,如果有一个图形窗口打开,那就是下一个"当前"设备.这意味着第二个打开的pdf连接将不再被dev.off()关闭,因为on.exit调用中将有一个short .

我通过将我的功能更改为:

myPlotFunc <- function(x,save=F){
    fnames <- paste(names(x),"pdf",sep=".")
    devs <- NULL
    on.exit(for(i in devs) dev.off(i), add=T)
    for(i in 1:length(x)){
      if(save){
        pdf(fnames[i])
        devs <- c(devs,dev.cur())
      }
      plot(x[[i]])
    }
    fnames
  }
Run Code Online (Sandbox Code Playgroud)

但这感觉很尴尬.有没有我在这里缺少的东西,或者更好的解决方法?

免责声明:

如果您不知道,请dev.off()在运行第三个代码块后运行.完成后,您可以通过运行轻松清理unlink(fnames).

Mar*_*rek 6

如何制作帮助功能来做一个情节:

myPlotFunc <- function(x, save=FALSE) {
    fnames <- paste(names(x), "pdf", sep=".")
    plot_one <- function(xx, fname, save=save) {
        if (save) {
            pdf(fname)
            on.exit(dev.off())
        }
        plot(xx)
    }
    for (i in 1:length(x)) plot_one(x[[i]], fnames[i], save)

    fnames
}
Run Code Online (Sandbox Code Playgroud)

  • 非常狡猾.最好将`1:length(x)`更改为`seq_along(x)`以避免当`x`的长度为0时出现问题. (3认同)