如何避免ggplotly修改ggmosaic facet_grid的标签格式?
问题:ggplot2 ggmosaic分面图转plotly后格式错乱的解决办法
将ggmosaic绘制的facet_grid传入plotly后,会出现以下格式问题:
- 覆盖ggplot的
theme()自定义设置 - 自动添加不必要的图例
- 轴标签被替换为默认的'x'和'y'
- 分面标签的文本对齐方式被打乱
复现代码
library(ggplot2) library(ggmosaic) library(plotly) HECdf <- as.data.frame(HairEyeColor) my.plot <- ggplot(data = HECdf) + geom_mosaic(aes(x = product(Eye, Hair), fill = Eye, weight = Freq), show.legend = FALSE) + theme_mosaic() + labs(title = 'Hair and Eye Color by Sex', caption = 'Source: HairEyeColor dataset (R)', x = "Hair Color", # 显式定义轴标签,避免plotly丢失 y = "Eye Color") + theme(axis.ticks.x = element_blank(), axis.ticks.y = element_blank(), axis.title.x = element_text(color = 'black', face = 'bold'), axis.title.y = element_text(color = 'black', vjust = 3, face = 'bold'), axis.text.x = element_text(color = 'black', angle = 45, hjust = 1), axis.text.y = element_text(color = 'black'), plot.title = element_text(hjust = 0.5, vjust = 2, face = 'bold'), plot.caption = element_text(hjust = 1), plot.margin = margin(t = 1, r = 1, b = 1, l = 1, unit = "cm")) + scale_fill_manual(values = c("#8B4513", "dodgerblue2", "darkgoldenrod", "#1e8449")) + facet_grid( ~ factor(Sex, levels = c('Female', 'Male')), scales = "free_x") my.plot my.fig <- ggplotly(my.plot) my.fig
环境配置
Rstudio version: 2024.04.1+748 R version: 4.4.0 (2024-04-24) Platform: aarch64-apple-darwin20 Running under: macOS Sonoma 14.5 packageVersion("plotly"): ‘4.10.4’ packageVersion("ggplot2"): ‘3.5.1’ packageVersion("ggmosaic"): ‘0.3.3’
解决方案
由于ggmosaic属于ggplot的扩展图层,plotly对其兼容性有限,需要通过plotly的layout()和style()函数手动修复格式问题:
- 移除多余图例
在ggplotly()中添加showlegend = FALSE参数,或者通过layout(showlegend = FALSE)强制关闭:
my.fig <- ggplotly(my.plot, showlegend = FALSE)
- 恢复自定义轴标签
plotly会丢失ggmosaic的轴标签,需要在layout()中显式设置:
my.fig <- my.fig %>% layout( xaxis = list(title = list(text = "Hair Color", font = list(color = "black", face = "bold"))), yaxis = list(title = list(text = "Eye Color", font = list(color = "black", face = "bold"))) )
- 修复文本样式与对齐
手动匹配ggplot中的主题设置,包括标题、轴文本、边距等:
my.fig <- my.fig %>% layout( title = list( text = 'Hair and Eye Color by Sex', x = 0.5, # 居中对齐 font = list(face = "bold") ), annotations = list( list( text = 'Source: HairEyeColor dataset (R)', x = 1, y = -0.15, # 右下角对齐 showarrow = FALSE, xref = "paper", yref = "paper", font = list(size = 10) ) ), margin = list(t = 100, r = 100, b = 100, l = 100), # 对应ggplot的1cm边距 xaxis = list( tickfont = list(color = "black"), tickangle = -45, # 反转角度适配plotly的文本对齐 ticks = "" # 隐藏轴刻度 ), yaxis = list( tickfont = list(color = "black"), ticks = "" # 隐藏轴刻度 ) )
- 修正分面标签对齐
plotly的分面标签默认对齐方式与ggplot不同,需要通过annotations手动调整位置:
my.fig <- my.fig %>% layout( annotations = append( .$x$layout$annotations, list( list(x = 0.25, y = 1.05, text = "Female", xref = "paper", yref = "paper", showarrow = FALSE), list(x = 0.75, y = 1.05, text = "Male", xref = "paper", yref = "paper", showarrow = FALSE) ) ) )
完整修正代码
library(ggplot2) library(ggmosaic) library(plotly) HECdf <- as.data.frame(HairEyeColor) my.plot <- ggplot(data = HECdf) + geom_mosaic(aes(x = product(Eye, Hair), fill = Eye, weight = Freq), show.legend = FALSE) + theme_mosaic() + labs(title = 'Hair and Eye Color by Sex', caption = 'Source: HairEyeColor dataset (R)', x = "Hair Color", y = "Eye Color") + theme(axis.ticks.x = element_blank(), axis.ticks.y = element_blank(), axis.title.x = element_text(color = 'black', face = 'bold'), axis.title.y = element_text(color = 'black', vjust = 3, face = 'bold'), axis.text.x = element_text(color = 'black', angle = 45, hjust = 1), axis.text.y = element_text(color = 'black'), plot.title = element_text(hjust = 0.5, vjust = 2, face = 'bold'), plot.caption = element_text(hjust = 1), plot.margin = margin(t = 1, r = 1, b = 1, l = 1, unit = "cm")) + scale_fill_manual(values = c("#8B4513", "dodgerblue2", "darkgoldenrod", "#1e8449")) + facet_grid( ~ factor(Sex, levels = c('Female', 'Male')), scales = "free_x") # 转换为plotly并修复格式 my.fig <- ggplotly(my.plot, showlegend = FALSE) %>% layout( title = list( text = 'Hair and Eye Color by Sex', x = 0.5, font = list(face = "bold") ), xaxis = list( title = list(text = "Hair Color", font = list(color = "black", face = "bold")), tickfont = list(color = "black"), tickangle = -45, ticks = "" ), yaxis = list( title = list(text = "Eye Color", font = list(color = "black", face = "bold")), tickfont = list(color = "black"), ticks = "" ), annotations = list( list( text = 'Source: HairEyeColor dataset (R)', x = 1, y = -0.15, showarrow = FALSE, xref = "paper", yref = "paper", font = list(size = 10) ), list(x = 0.25, y = 1.05, text = "Female", xref = "paper", yref = "paper", showarrow = FALSE), list(x = 0.75, y = 1.05, text = "Male", xref = "paper", yref = "paper", showarrow = FALSE) ), margin = list(t = 100, r = 100, b = 100, l = 100), showlegend = FALSE ) my.fig
内容的提问来源于stack exchange,提问作者inter_naut
相关产品推荐
相关产品推荐

