我遇到了一個相當惱人的問題,打開設備列表,試圖構造一個函數,爲列表保存大量圖形。假設我們有以下數據:瞭解如何讀取設備列表
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)
)
及以下功能:
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
}
如果我運行fnames <- myPlotFunc(Alist,save=T)
,一切都可以正常工作,我得到3 PDF文件名稱X1.pdf
到X3.pdf
。也就是說,如果沒有圖形窗口打開。如果有,則其中一個pdf未關閉,隨後所有後續圖都將添加到pdf中,直到我在控制檯中明確調用dev.off()
。就像這樣:
plot(Alist[[1]])
fnames <- myPlotFunc(Alist,save=T)
myPlotFunc(Alist,save=F)
> dev.list()
pdf
4
如果我添加on.exit({print(dev.cur());dev.off()},add=T)
,我獲得以下的輸出:
> fnames <- myPlotFunc(Alist,save=T)
pdf
5
windows
2
pdf
3
因此很明顯,它從下往上列表中再次關閉它符合一切。所以如果有一個圖形窗口打開,那就是下一個「當前」設備。這意味着第二個最後打開的pdf連接將不會被dev.off()函數關閉,因爲在on.exit
調用中會有一條短路。
我周圍有改變我的功能:
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
}
但這種感覺相當尷尬。我在這裏錯過了什麼,或者有更好的方法來解決這個問題?
免責聲明:
如果你不知道,在運行第三個代碼塊後運行dev.off()
。完成後,您可以通過運行unlink(fnames)
輕鬆清理。
好的建議,我沒有想到。看起來比我的解決方案更清潔。 – 2011-04-14 15:47:09
+1迄今爲止提供的最好的解決方案和最乾淨的解決方案,現有設備的最小副作用(無)! – 2011-04-14 15:50:54
非常狡猾。最好將'1:length(x)'改爲'seq_along(x)',以避免'x'長度爲0的問題。 – 2011-04-14 16:03:59