R语言函数调用与逐行执行生成SVG图结果不一致问题
问题:批量执行R脚本生成空白SVG,逐行执行正常
在main.R中调用eda(ds)时,批量执行整个脚本会导致输出的density_age.svg为空白文件,但逐行选中代码按Ctrl+Enter执行时,能生成正常的图像。已确认两次执行使用的ds数据一致,代码全程无报错。
相关代码
主调用代码
ds <- eda(ds)
eda函数定义
eda <- function(ds){ log4r.info(eda_logger, "Prepping data") ds <- prep.data(ds) log4r.info(eda_logger, "Feature selection") ds <- feature.selection(ds) log4r.info(eda_logger, "Univariate Descriptive Statistics Graph") univariate.descriptive.statistics.graph(ds) return(ds) }
(注:原代码函数名误写为teda,已修正为调用时的eda)
绘图函数定义
univariate.descriptive.statistics.graph <- function(ds){ # Density out_density_path <- paste0(out_graph, "/density_age.svg") #line 1 svg(out_density_path) #line 2 lattice::densityplot(ds$age, xlab="Age") #line 3 dev.off() #line 4 }
补充数据样本
> dput(head(ds, 20)) structure(list(gender = structure(c(2L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L), .Label = c("Female", "Male", "Other"), class = "factor"), age = c(67, 61, 80, 49, 79, 81, 74, 69, 59, 78, 81, 61, 54, 78, 79, 50, 64, 75, 60, 57 ), hypertension = c(0L, 0L, 0L, 0L, 1L, 0L, 1L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 0L, 0L), heart_disease = c(1L, 0L, 1L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 1L, 0L, 1L, 0L, 0L, 1L), avg_glucose_level = c(228.69, 202.21, 105.92, 171.23, 174.12, 186.21, 70.09, 94.39, 76.15, 58.57, 80.43, 120.46, 104.51, 219.84, 214.09, 167.41, 191.61, 221.29, 89.22, 217.08), bmi = c(36.6, NA, 32.5, 34.4, 24, 29, 27.4, 22.8, NA, 24.2, 29.7, 36.8, 27.3, NA, 28.2, 30.9, 37.5, 25.8, 37.8, NA), smoking_status = structure(c(1L, 2L, 2L, 3L, 2L, 1L, 2L, 2L, NA, NA, 2L, 3L, 3L, NA, 2L, 2L, 3L, 3L, 2L, NA), .Label = c("formerly smoked", "never smoked", "smokes" ), class = "factor"), stroke = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L)), row.names = c(NA, 20L), class = "data.frame")
原因与解决方法
这是lattice绘图系统在函数内批量执行时的典型问题:lattice绘图默认采用延迟求值,在函数内部如果没有显式触发打印,绘图对象不会被渲染到输出设备上。逐行执行时R会自动打印绘图对象,所以能正常生成图像;但批量执行函数时,这个自动打印步骤被跳过,导致dev.off()关闭设备前没有实际绘制内容,最终生成空白文件。
有两种简单的修复方式:
方法1:显式打印lattice绘图对象
修改绘图函数,将densityplot的结果赋值给变量并打印:
univariate.descriptive.statistics.graph <- function(ds){ out_density_path <- paste0(out_graph, "/density_age.svg") svg(out_density_path) # 显式打印绘图对象 p <- lattice::densityplot(ds$age, xlab="Age") print(p) dev.off() }
方法2:全局启用lattice自动打印
在脚本开头添加一行代码,全局开启lattice绘图的自动打印功能:
lattice::trellis.device()
这种方法无需修改现有绘图函数,适合存在多个lattice绘图的场景。
内容的提问来源于stack exchange,提问作者IDK
相关产品推荐
相关产品推荐

