为何ggplot的scale_manual扩展图例项在ggplotly中无法正常显示?
ggplot扩展图例项在ggplotly中丢失的解决办法
问题场景
在ggplot中使用scale_color_manual的limits参数扩展图例,加入数据中不存在的取值(比如示例中的"10"),可以正常显示包含"ten"的完整图例,但用ggplotly()渲染后,新增的图例项会丢失。
原测试代码:
lims <- c("4", "6", "8", "10") cols <- c("4" = "blue", "6" = "darkgreen", "8" = "red", "10" = "orange") labs <- c("4" = "four", "6" = "six", "8" = "eight", "10" = "ten") p <- ggplot(mtcars, aes(mpg, wt)) + geom_point(aes(color = factor(cyl))) q <- p + scale_color_manual(name = "Cylinder", values = cols, labels = labs, limits = lims) # ggplot中正常显示完整图例 q # ggplotly渲染后丢失"ten"图例项 ggplotly(q)
解决方法
方法1:添加geom_blank层保留缺失水平
ggplotly会过滤掉无对应数据点的图例类别,通过添加geom_blank(空数据点)让它识别到该类别的存在,从而保留图例项。修改后的代码如下:
lims <- c("4", "6", "8", "10") cols <- c("4" = "blue", "6" = "darkgreen", "8" = "red", "10" = "orange") labs <- c("4" = "four", "6" = "six", "8" = "eight", "10" = "ten") # 将cyl转换为包含所有目标水平的因子 mtcars$cyl_factor <- factor(mtcars$cyl, levels = lims) p <- ggplot(mtcars, aes(mpg, wt)) + geom_point(aes(color = cyl_factor)) + # 添加空数据点对应缺失的"10"水平 geom_blank(aes(color = "10")) + scale_color_manual(name = "Cylinder", values = cols, labels = labs, limits = lims) # ggplot和ggplotly均能显示完整图例 p ggplotly(p)
方法2:手动修改plotly对象
如果不想改动ggplot代码,可以在生成ggplotly对象后,手动插入缺失的图例项:
lims <- c("4", "6", "8", "10") cols <- c("4" = "blue", "6" = "darkgreen", "8" = "red", "10" = "orange") labs <- c("4" = "four", "6" = "six", "8" = "eight", "10" = "ten") p <- ggplot(mtcars, aes(mpg, wt)) + geom_point(aes(color = factor(cyl))) q <- p + scale_color_manual(name = "Cylinder", values = cols, labels = labs, limits = lims) # 生成ggplotly对象 ply <- ggplotly(q) # 手动添加"ten"图例项 ply$x$data <- c(ply$x$data, list( list( type = "scatter", mode = "markers", marker = list(color = cols["10"]), name = labs["10"], showlegend = TRUE, x = numeric(0), y = numeric(0) ) )) # 渲染修改后的plotly对象 ply
原理说明
ggplotly默认会自动过滤掉没有对应数据点的图例类别,通过geom_blank添加空数据点,或者手动插入空的散点图层,可以让plotly识别到该类别的存在,从而保留对应的图例项。
内容的提问来源于stack exchange,提问作者BTT
相关产品推荐
相关产品推荐

