在函数内保存 mirt 的绘图

问题描述 投票:0回答:2

我在使用 R 的 mirt 包时保存函数内部生成的图时遇到了一个奇怪的问题。这是一个代表:

#save image from base plot
save_as_file = function(code, filename, width = 1000, height = 750) {
  png(filename, width = width, height = height)
  eval(substitute(code))
  dev.off()
  try(dev.off(), silent = T)
}

#test it
plot(1:3)
save_as_file(plot(1:3), "test.png")
#> null device 
#>           1
file.remove("test.png")
#> [1] TRUE

这使得这个情节:

但是,当我尝试将它与 mirt 一起使用时,什么也没有产生:

#mirt test
library(mirt)
#> Loading required package: stats4
#> Loading required package: lattice
set.seed(1)
mirt_data = mirt::simdata(
  a = c(1:4),
  d = c(0,0,1,1),
  N = 1000,
  itemtype = "2PL"
)
mirt_fit = mirt(
  data = mirt_data,
  model = 1,
  itemtype = "2PL",
  verbose = F
)
plot(mirt_fit, type = "trace") #works
save_as_file(plot(mirt_fit, type = "trace"), "mirt.png") #nothing happens
#> null device 
#>           1

生成此图,但没有保存文件。为什么?

r plot lattice r-base-graphics
2个回答
0
投票

事实证明很简单。出于某种原因,必须在函数内显式打印绘图。这有效:

#save image from base plot
save_as_file = function(code, filename, width = 1000, height = 750) {
  png(filename, width = width, height = height)
  print(eval(substitute(code)))
  dev.off()
  try(dev.off(), silent = T)
}

save_as_file(plot(mirt_fit, type = "trace"), "mirt.png")
file.remove("mirt.png")

0
投票

正如您已经发现的那样,您必须神秘地使用

print
。原因是
plot(mirt_fit,...)
派遣到
mirt:::plot_mixture(mirt_fit, ...)
使用
lattice
.

lattice
函数的行为与标准 R 图形函数不同,因为它们在执行时不会立即创建绘图。相反,像传统函数一样,它们创建一个类
"trellis"
的对象,并且使用打印方法
print.trellis
创建绘图(ggplot 可能抄袭了这一点)。因此,可能需要明确地
print
(在这种情况下发送到
lattice:::print.trellis
)对象来显示情节。

你提出的解决方案有一个小问题;如果在绘图过程中出现错误,它不会关闭

png
设备,并且会随着时间的推移弄乱您的设备列表。

graphics.off()
dev.list()
# NULL
save_as_file(plot(stop(), type="trace"), "mirt.png")
# Error ...
save_as_file(plot(stop(), type="trace"), "mirt.png")
# Error ...
dev.list()
# png png 
#   2   3 
graphics.off()

所以最好在

dev.off()
中使用
on.exit()
。我们也可以使用案例处理,以避免基础 R
plot
s 被
print
ed.

save_as_file <- function(code, filename, width=1000, height=750) {
  on.exit(dev.off())
  png(filename, width=width, height=height)
  p <- eval(substitute(code))
  if (!is.null(p)) print(p)
}

save_as_file(mirt:::plot_mixture(stop(), type="trace"), "mirt.png")
dev.list()  ## no device open
# NULL
save_as_file(plot(mirt_fit, type="trace"), "mirt.png")
save_as_file(plot(1:3), "mirt.png")
© www.soinside.com 2019 - 2024. All rights reserved.