Я столкнулся с довольно раздражающей проблемой со списком открытых устройств, пытаясь создать функцию, которая сохраняет ряд графиков для списка.Скажем, у нас есть следующие данные:
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
Так что, очевидно, для закрытия всего, что встречается, требуется список снизу вверх.Таким образом, если открыто графическое окно, это следующее «текущее» устройство.Это значит, что dev.off () больше не будет закрывать второе открытое pdf-соединение, так как в вызове 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)
, когда вы закончите.