ggplot2箱图转ggplotly后宽度与annotate注释失效的修复方案
修复ggplot2转ggplotly后箱图宽度与注释失效的问题
问题背景
使用ggplot2的geom_boxplot绘制单变量箱图并设置宽度为0.05,同时用annotate添加统计摘要文本注释,但调用ggplotly()转换后,箱图宽度设置和文本注释均失效。
方案1:基于ggplot2的适配修复
ggplotly对未指定x映射的单变量箱图处理存在兼容问题,同时annotate的绝对x坐标在转换时会被重置。可通过给x轴指定固定映射值解决:
library(ggplot2) library(plotly) # 数据保持不变 throu<-structure(list(case_id = c("WC4132791", "WC4130879", "WC4128064", "WC4121569", "WC4121568", "WC4130112", "WC4131829", "WC4130841", "WC4130306", "WC4130417", "WC4124741", "WC4130114", "WC4131990", "WC4121986", "WC4128062", "WC4122478", "WC4130337", "WC4125822", "WC4127231", "WC4124761", "WC4129398", "WC4131040", "WC4123072", "WC4131822", "WC4120712", "WC4121978", "WC4130110", "WC4123522", "WC4130307", "WC4122643", "WC4130383", "WC4122248", "WC4122299", "WC4122727", "WC4126769", "WC4131186", "WC4125978", "WC4129089", "WC4121339", "WC4126469", "WC4131800", "WC4125572", "WC4132378", "WC4123345", "WC4130314", "WC4127722", "WC4129978", "WC4131838", "WC4130812", "WC4126953"), throughput_time = c(134.283333333333, 93.0756944444445, 83.5340277777778, 67.7833333333333, 65.3069444444444, 63.5402777777778, 59.6861111111111, 56.9791666666667, 55.9048611111111, 54.3826388888889, 52.6958333333333, 52.5125, 51.1680555555556, 50.9520833333333, 50.5402777777778, 49.9291666666667, 49.8201388888889, 49.7375, 49.0916666666667, 46.3069444444444, 45.30625, 45.2451388888889, 44.9722222222222, 44.8215277777778, 44.8048611111111, 43.0701388888889, 42.6840277777778, 42.6576388888889, 42.55, 42.2868055555556, 42.2805555555556, 41.9027777777778, 41.7409722222222, 41.6506944444444, 41.3527777777778, 40.7305555555556, 40.2861111111111, 40.2159722222222, 40.0854166666667, 40.0486111111111, 39.7930555555556, 39.6576388888889, 39.4638888888889, 39.4527777777778, 39.3569444444444, 39.3513888888889, 39.1854166666667, 39.0791666666667, 39.0743055555556, 39.0055555555556 )), row.names = c(NA, 50L), class = "data.frame") quarts<- structure(list(min = 0, q1 = 7.1515625, median = 11.4881944444444, mean = 12.3112423835125, q3 = 14.8456597222222, max = 93.0756944444445, st_dev = 6.72704434885421, iqr = 7.69409722222222), class = "data.frame", row.names = c(NA, -1L)) # 修改后的ggplot代码 p<-ggplot(throu, aes(x = 1, y=throughput_time)) + geom_boxplot(fill="steelblue", alpha=0.2, width=0.05) + annotate(geom = 'text', x = 1.02, y = 60, hjust = 0, color = 'gray50', label = paste(names(quarts), collapse = '\n')) + annotate(geom = 'text', x = 1.05, y = 60, hjust = 0, label = paste(round(unlist(quarts), 3), collapse = '\n')) + xlim(0.9, 1.2) + xlab("")+ylab("Case duration in days")+ theme_classic()+ theme(axis.ticks.x = element_blank(), axis.text.x = element_blank()) # 转换为ggplotly ggplotly(p)
关键修改点:
- 给
aes添加固定x映射x=1,让ggplotly能正确识别箱图的位置和宽度 - 调整
annotate的x坐标为1附近的相对值,避免转换时坐标丢失 - 修改
xlim范围以适配新的x轴映射,同时保证注释可见
方案2:纯Plotly实现(避免转换兼容问题)
直接使用Plotly原生函数构建箱图和注释,彻底规避ggplot2到plotly的转换问题:
library(plotly) # 数据保持不变 throu<-structure(list(case_id = c("WC4132791", "WC4130879", "WC4128064", "WC4121569", "WC4121568", "WC4130112", "WC4131829", "WC4130841", "WC4130306", "WC4130417", "WC4124741", "WC4130114", "WC4131990", "WC4121986", "WC4128062", "WC4122478", "WC4130337", "WC4125822", "WC4127231", "WC4124761", "WC4129398", "WC4131040", "WC4123072", "WC4131822", "WC4120712", "WC4121978", "WC4130110", "WC4123522", "WC4130307", "WC4122643", "WC4130383", "WC4122248", "WC4122299", "WC4122727", "WC4126769", "WC4131186", "WC4125978", "WC4129089", "WC4121339", "WC4126469", "WC4131800", "WC4125572", "WC4132378", "WC4123345", "WC4130314", "WC4127722", "WC4129978", "WC4131838", "WC4130812", "WC4126953"), throughput_time = c(134.283333333333, 93.0756944444445, 83.5340277777778, 67.7833333333333, 65.3069444444444, 63.5402777777778, 59.6861111111111, 56.9791666666667, 55.9048611111111, 54.3826388888889, 52.6958333333333, 52.5125, 51.1680555555556, 50.9520833333333, 50.5402777777778, 49.9291666666667, 49.8201388888889, 49.7375, 49.0916666666667, 46.3069444444444, 45.30625, 45.2451388888889, 44.9722222222222, 44.8215277777778, 44.8048611111111, 43.0701388888889, 42.6840277777778, 42.6576388888889, 42.55, 42.2868055555556, 42.2805555555556, 41.9027777777778, 41.7409722222222, 41.6506944444444, 41.3527777777778, 40.7305555555556, 40.2861111111111, 40.2159722222222, 40.0854166666667, 40.0486111111111, 39.7930555555556, 39.6576388888889, 39.4638888888889, 39.4527777777778, 39.3569444444444, 39.3513888888889, 39.1854166666667, 39.0791666666667, 39.0743055555556, 39.0055555555556 )), row.names = c(NA, 50L), class = "data.frame") quarts<- structure(list(min = 0, q1 = 7.1515625, median = 11.4881944444444, mean = 12.3112423835125, q3 = 14.8456597222222, max = 93.0756944444445, st_dev = 6.72704434885421, iqr = 7.69409722222222), class = "data.frame", row.names = c(NA, -1L)) # 构建plotly箱图 fig <- plot_ly(throu, y = ~throughput_time, type = "box", width = 0.05, # 设置箱图宽度 fillcolor = "steelblue", opacity = 0.2) %>% layout(yaxis = list(title = "Case duration in days"), xaxis = list(visible = FALSE), # 隐藏x轴刻度和标签 showlegend = FALSE) # 添加统计注释 labels_names <- paste(names(quarts), collapse = "<br>") labels_values <- paste(round(unlist(quarts), 3), collapse = "<br>") fig <- fig %>% add_annotations(x = 1.02, y = 60, xref = "x", yref = "y", text = labels_names, font = list(color = "gray50"), showarrow = FALSE, xanchor = "left") %>% add_annotations(x = 1.05, y = 60, xref = "x", yref = "y", text = labels_values, showarrow = FALSE, xanchor = "left") %>% layout(xaxis = list(range = c(0.9, 1.2))) # 调整x轴范围显示注释 fig
优势:
- 完全基于Plotly原生API,不存在转换兼容问题
- 注释和箱图宽度设置直接生效,无需额外适配
内容的提问来源于stack exchange,提问作者firm
相关产品推荐
相关产品推荐

