如何以编程且非破坏性方式判断当前图形设备是否为基础图形?
问题
是否存在一种编程方式且非破坏性的方法,判断当前图形设备是否处于基础图形(base graphics)环境?要求该方法不得打开/关闭设备,也不能对设备进行任何修改(比如添加图形元素)。
现有尝试的局限
用户给出了一个初步尝试的函数:
isbasegx <- function() { length(dev.list()) > 0 && !identical(par("usr"), c(0, 1, 0, 1)) }
但这类依赖par()的方法存在明显缺陷:基于grid的图形(比如ggplot)不会更新par()的参数,即使在同一设备上绘制了ggplot,par()的返回值和base图形绘制后完全一致,导致判断失效。示例如下:
plot(1, 1) par1 <- par() ggplot(mtcars, aes(mpg, disp)) # 同一设备绘制grid图形 par2 <- par() all(mapply(identical, par1, par2)) # [1] TRUE
可行的判断方法
方法1:利用grid包的上下文检测
grid图形环境下可以通过grid::grid.current()获取当前绘图对象,而base图形环境下调用该函数会抛出错误。结合tryCatch可以实现无修改判断:
is_base_graphics <- function() { # 先判断是否有活跃设备 if (length(dev.list()) == 0) return(FALSE) # 尝试获取grid上下文,报错则说明是base图形 grid_ctx <- tryCatch(grid::grid.current(), error = function(e) NULL) is.null(grid_ctx) }
测试效果:
# 测试base图形 plot(1, 1) is_base_graphics() # [1] TRUE # 测试ggplot(grid环境) library(ggplot2) ggplot(mtcars, aes(mpg, disp)) is_base_graphics() # [1] FALSE # 无活跃设备时 dev.off() is_base_graphics() # [1] FALSE
方法2:通过绘图记录的类型判断
base图形的绘图记录是recordedplot类对象,而grid图形的记录是grid.record类。利用recordPlot()获取记录后判断类型:
is_base_graphics2 <- function() { if (length(dev.list()) == 0) return(FALSE) plot_rec <- tryCatch(recordPlot(), error = function(e) NULL) if (is.null(plot_rec)) return(FALSE) inherits(plot_rec, "recordedplot") }
该方法同样非破坏性,仅读取当前绘图状态,不会修改设备。
补充说明
- 方法1更轻量,无需生成完整绘图记录;
- 两种方法都兼容交互式设备和非交互式设备(比如生成报告用的pdf/png设备)。
内容的提问来源于stack exchange,提问作者r2evans
相关产品推荐
相关产品推荐

