R语言自定义函数中正确使用identify存储绘图点选结果
自定义函数中调用
identify无法正常触发点选交互的解决方法 问题根源
代码无法稳定触发点选是三个原因共同导致的:
%>%管道链式嵌套identify会改变执行上下文环境,identify依赖绘图设备实时处于交互就绪状态,管道执行时不会等待画布渲染完成就继续运行后续逻辑,直接跳过交互步骤mapply批量执行绘图逻辑时,没有强制刷新绘图缓冲区,后续绘图指令会直接覆盖等待交互的状态,只有偶发时序匹配时才会正常进入点选- 管道内用
with(.)传参,无法把正确的绘图坐标数据稳定传给identify,进一步降低了交互触发概率
修正后可稳定运行的实现
核心调整点:
- 放弃管道+
mapply的嵌套写法,用循环拆分「绘图、加参考线、刷新画布、点选」四个步骤,避免环境错乱 - 每绘制完一张图调用
dev.flush()强制刷新绘图缓冲区,确保画布完全渲染后再启动点选 - 单独设置向量存储所有点选结果,最终返回整理好的标签向量
library(tidyverse) library(faraway) some_func <- function(data, response, predictors, label){ form <- reformulate(predictors, response=response) mod <- lm(form, data) dfb_mod <- dfbeta(mod)[,-1] %>% data.frame() %>% as.list() # 设置绘图布局 par(mfrow=c(2, 2), ask=FALSE) xlabel <- names(dfb_mod) ident_labels <- data[, label] # 初始化存储点选结果的向量 selected_points <- c() # 逐图绘制+点选 for (i in seq_along(dfb_mod)) { x_val <- dfb_mod[[i]] x_lab <- xlabel[i] # 绘制散点 plot(x_val, xlab=x_lab, ylab='DFBETA值', main=paste0("DFBETA指标:", x_lab)) # 添加0参考线 abline(h=0, col="red", lty=2) # 强制刷新绘图设备,确保画布渲染完成 dev.flush() # 等待点选,点完按ESC/右键停止 picked_idx <- identify(x_val, labels=ident_labels, n=length(x_val)) # 追加当前图选中的标签到结果向量 selected_points <- c(selected_points, ident_labels[picked_idx]) } # 还原默认绘图布局 par(mfrow=c(1,1)) # 返回去重后的点选结果 return(unique(selected_points)) } # 测试运行 data(savings) savings2 <- savings %>% rownames_to_column() picked_res <- some_func(savings2, 'sr', c('pop15', 'pop75', 'dpi', 'ddpi'), 'rowname') # 查看选中的点标签 print(picked_res)
使用注意事项
- 函数运行后会逐张渲染子图,每完成一张画布的渲染,即可用鼠标点击需要标记的点;当前图点选完成后,按右键选择「停止」或按ESC键,会自动进入下一张图的点选流程
- 如果需要单独留存每张子图的点选结果,可以把存储结果的
selected_points改为列表类型,按子图顺序分别存储即可 - 如果需要固定每个子图最多选N个点,可以给
identify()加n=N参数,选满N个点后会自动进入下一张图,不需要手动按停止
内容的提问来源于stack exchange,提问作者Emil11
相关产品推荐
相关产品推荐

