如何在 R 中创建基于离屏(位图)图形的“交互式”图形设备?

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

在 R 中绘制大图可能会非常慢。我正在尝试一些解决方法,但即使使用最大缓冲的“dbcairo”X11 设备,绘图似乎也比实际需要的时间要长得多。我注意到“png”设备对于小地块和大地块来说速度更快。

小图,png() 比 X11() 快约 3 倍:

> system.time({X11(type="dbcairo"); plot(1:1e3); dev.off()})
   user  system elapsed 
  0.234   0.029   0.373 
> system.time({png("file.png",type="cairo"); plot(1:1e3); dev.off()})
   user  system elapsed 
  0.114   0.000   0.113 
> system.time({png("file.png",type="Xlib"); plot(1:1e3); dev.off()})
   user  system elapsed 
  0.056   0.000   0.107 

大图,png() 击败 X11() 2.3 倍到 46 倍:

> system.time({X11(type="dbcairo"); plot(1:1e5); dev.off()})
   user  system elapsed 
 14.420   0.157  15.491 
> system.time({png("file.png",type="cairo"); plot(1:1e5); dev.off()})
   user  system elapsed 
  6.790   0.001   6.826 
> system.time({png("file.png",type="Xlib"); plot(1:1e5); dev.off()})
   user  system elapsed 
  0.144   0.010   0.340 

结果与其他 X11() 设备类型(类似于“dbcairo”)和其他位图图像类型(类似于“png”)几乎相同。我猜测 png() 类型“cairo”比“Xlib”需要更长的时间,因为它会产生抗锯齿输出。

对于中等大小的 ggplot2 图,我发现 png() 比 X11() 快 1.7 倍到 2.6 倍(这是使用

png(..); plot(g); dev.off()
,而不是
ggsave()

由于我可以使用像“feh”这样的极简图像查看器几乎立即加载和重新加载 PNG 文件,所以我想知道为什么我不使用 png() 作为 R 的主要绘图设备。

问题当然是,在我调用 dev.off() 之前,PNG 文件不会写入磁盘。这限制了标准绘图界面的风格,我在其中设置设备一次,然后显示各种绘图,有时添加线条或文本,同时在绘图窗口中立即查看每个更改。

创建一个新的 R 图形设备,将图像文件写入 PNG(或其他一些图像格式),但使用像“feh”这样的简单图像查看器在每个绘图命令后显示它们,会不会很困难?换句话说,我正在寻找像 X11 这样的“交互式”绘图设备,但它使用现有设备的位图离屏渲染工具(例如 png()、jpeg() 或 tiff())来绘制图像。或者也许可以修改 png() 设备以具有赋予其这种行为的选项。 (或者也许我应该使用 knitR 来做所有事情......但我更熟悉命令行......)

r plot graphics bitmap
2个回答
1
投票

如果 X11 让您感到厌烦,并且您不想使用 RStudio 绘图查看器(或者因为您位于无法安装 RStudio Server 的远程服务器上而无法使用),一个有趣的替代方案是使用

rmote
包。您可以将其安装在您自己的本地 R 安装上,或者如果您通过 SSH 连接到远程计算机并愿意转发端口,则可以将其安装在远程 R 实例上。然后,您打印的任何绘图和帮助文件都将被重定向到本地网络服务器,您可以在其中从浏览器访问它们。

它还带有一些不错的附加功能,例如:

  • 情节历史,
  • 右键单击并保存绘图的能力,就像浏览器中的任何其他图像一样,并且
  • 能够选择将哪种类型的输出发送到服务器。

我发现这是 X11 在远程服务器上进行绘图转发的一个很好的替代方案,并且它在本地也运行良好 🙂


0
投票

您应该可以通过设置

device
选项来做到这一点,如下所示:

options(device = function() {
  file <- tempfile("last_plot_", fileext = ".png")
  png(file)

  # This gets run at the *very* end:
  withr::defer(
    {
      dev.off()
      system2("feh", file)
    }, 
    sys.frame(1)
  )
})

请注意,我没有安装

feh
,所以我还没有测试上述内容是否按预期工作。如果没有,您可能需要将呼叫调整为
system2()

就我个人而言,我发现系统默认的图像查看器已经足够了,为了更快的渲染,我还喜欢使用 {ragg} 包。这给出了这样的东西:

options(device = function() {
  file <- tempfile("last_plot_", fileext = ".png")

  ragg::agg_png(file, height = 480 * 5, width = 480 * 5, scaling = 5)

  withr::defer(
    {
      dev.off()
      browseURL(file)
    }, 
    sys.frame(1)
  )
})
© www.soinside.com 2019 - 2024. All rights reserved.