ggplotly高亮selectize控件显示异常:与geom图层顺序有关?
ggplotly反转geom图层后selectize高亮控件异常的问题
我需要制作一个具备以下功能的交互式散点图:
- 高亮单个数据点
- 鼠标悬停时tooltip显示id
- 通过selectize widget搜索特定id
原始可用代码如下:
library(tidyverse) library(plotly) set.seed(1) dat <- tibble(id = LETTERS[1:10], trt = factor(rep(0:1, 5)), x = rnorm(10), y = x + rnorm(10, sd = 0.2)) %>% highlight_key(~id) dat %>% {ggplot(., aes(x = x, y = y, group = id, color = trt)) + geom_point() + geom_hline(yintercept = 0, linetype = "dashed")} %>% ggplotly(tooltip = c("id")) %>% highlight(on = "plotly_hover", selectize = TRUE)
当我尝试反转geom图层顺序(让hline在数据点后方)时,出现了两个异常:
- 不设置颜色映射时,selectize控件完全消失:
## no color, geom order reversed ## => selectize.js widget is completely missing dat %>% {ggplot(., aes(x = x, y = y, group = id)) + geom_hline(yintercept = 0, linetype = "dashed") + geom_point()} %>% ggplotly(tooltip = c("id")) %>% highlight(on = "plotly_hover", selectize = TRUE)
- 按trt设置颜色映射时,selectize控件仅对trt=0的数据生效:
## color by trt, geom order reversed ## => selectize.js widget only works for data where trt = 0 dat %>% {ggplot(., aes(x = x, y = y, group = id, color = trt)) + geom_hline(yintercept = 0, linetype = "dashed") + geom_point()} %>% ggplotly(tooltip = c("id")) %>% highlight(on = "plotly_hover", selectize = TRUE)
异常原因
ggplotly转ggplot为plotly对象时,是按图层顺序生成对应的trace的。geom_hline会变成一个独立的非数据trace,把它放在点图层前面时,会搞乱highlight_key绑定的分组trace识别逻辑:
- 没设颜色映射时,所有点会被合并成一个trace,但plotly的
highlight会优先认第一个数据相关的trace,这时第一个是geom_hline,自然就生成不了selectize控件。 - 按trt设颜色时,数据会分成两个trace(trt=0和trt=1),但plotly只会把第一个数据trace(trt=0)加到selectize的可选列表里,后面的trt=1就被忽略了。
解决方案
不在ggplot层面添加geom_hline,而是在ggplotly转换完成后,使用plotly的add_hline方法添加水平线。这样不会干扰数据trace的分组结构,确保highlight_key和selectize控件正常工作:
无颜色映射的修正代码
dat %>% {ggplot(., aes(x = x, y = y, group = id)) + geom_point()} %>% ggplotly(tooltip = c("id")) %>% add_hline(yintercept = 0, linetype = "dashed") %>% highlight(on = "plotly_hover", selectize = TRUE)
按trt设置颜色映射的修正代码
dat %>% {ggplot(., aes(x = x, y = y, group = id, color = trt)) + geom_point()} %>% ggplotly(tooltip = c("id")) %>% add_hline(yintercept = 0, linetype = "dashed") %>% highlight(on = "plotly_hover", selectize = TRUE)
这样既实现了水平线在数据点后方的效果,又能保证所有高亮和selectize功能正常运行。
内容的提问来源于stack exchange,提问作者retodomax
相关产品推荐
相关产品推荐

