You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免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()函数手动修复格式问题:

  1. 移除多余图例
    在ggplotly()中添加showlegend = FALSE参数,或者通过layout(showlegend = FALSE)强制关闭:
my.fig <- ggplotly(my.plot, showlegend = FALSE)
  1. 恢复自定义轴标签
    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")))
  )
  1. 修复文本样式与对齐
    手动匹配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 = ""  # 隐藏轴刻度
    )
  )
  1. 修正分面标签对齐
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 14:35:59