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

使用ggplotly添加双Y轴并实现柱状图标签显示需求

解决方案:双Y轴柱状图+Plotly标签兼容处理

一、双Y轴实现思路

要给Nb_diff添加第二Y轴,核心是手动对齐刻度映射:将差值数据按主Y轴的范围比例缩放,再通过sec_axis反向转换得到真实差值刻度,具体步骤如下:

1. 数据预处理(示例结构)

假设你的数据包含月份、正数值、负数值、Nb_diff字段,先确保格式正确:

# 替换为你的实际数据读取代码
df <- data.frame(
  月份 = c("1月", "2月", "3月", "4月"),
  正数值 = c(15, 22, 18, 25),
  负数值 = c(-8, -12, -9, -15),
  Nb_diff = c(7, 10, 9, 10)
)

2. 绘制带双Y轴的ggplot图表

library(ggplot2)

p <- ggplot(df, aes(x = 月份)) +
  # 绿色正柱
  geom_col(aes(y = 正数值), fill = "#2ecc71", width = 0.4) +
  # 红色负柱
  geom_col(aes(y = 负数值), fill = "#e74c3c", width = 0.4) +
  # 柱顶显示数值
  geom_text(aes(y = 正数值, label = 正数值), vjust = -0.5, size = 4) +
  geom_text(aes(y = 负数值, label = abs(负数值)), vjust = 1.5, size = 4) +
  # 蓝色Nb_diff标记(缩放后绑定主Y轴)
  geom_point(aes(y = Nb_diff * (max(正数值)/max(Nb_diff))), color = "#3498db", size = 3) +
  # 设置双Y轴
  scale_y_continuous(
    name = "正负数值",
    sec.axis = sec_axis(~ . / (max(df$正数值)/max(df$Nb_diff)), name = "Nb_diff差值")
  ) +
  labs(title = "月度正负数值与差值对比", x = "月份") +
  theme_minimal()

二、geom_label与Plotly兼容解决办法

geom_label转Plotly时易丢失样式,推荐两种可靠方案:

方案1:用Plotly原生函数添加标签

先将ggplot转为Plotly对象,再通过add_annotations批量添加差值标签:

library(plotly)

p_plotly <- ggplotly(p)

# 循环添加Nb_diff标签
for (i in 1:nrow(df)) {
  p_plotly <- p_plotly %>%
    add_annotations(
      x = df$月份[i],
      y = df$Nb_diff[i] * (max(df$正数值)/max(df$Nb_diff)),
      text = as.character(df$Nb_diff[i]),
      showarrow = FALSE,
      font = list(color = "#3498db", size = 14)
    )
}

p_plotly

方案2:用ggtext包替代geom_label

ggtext的geom_richtext支持HTML样式,且与Plotly兼容性更好:

library(ggtext)

# 替换原geom_label为geom_richtext
p <- p +
  geom_richtext(aes(y = Nb_diff * (max(正数值)/max(Nb_diff)), label = Nb_diff),
                fill = "white", color = "#3498db", label.size = 0, size = 4)

# 直接转为Plotly
ggplotly(p)

三、完整可运行代码

library(ggplot2)
library(plotly)
library(ggtext)

# 读取数据(替换为你的数据路径)
# df <- read.csv("your_data.csv")

# 示例数据
df <- data.frame(
  月份 = c("1月", "2月", "3月", "4月"),
  正数值 = c(15, 22, 18, 25),
  负数值 = c(-8, -12, -9, -15),
  Nb_diff = c(7, 10, 9, 10)
)

# 构建ggplot
p <- ggplot(df, aes(x = 月份)) +
  geom_col(aes(y = 正数值), fill = "#2ecc71", width = 0.4) +
  geom_col(aes(y = 负数值), fill = "#e74c3c", width = 0.4) +
  geom_text(aes(y = 正数值, label = 正数值), vjust = -0.5, size = 4) +
  geom_text(aes(y = 负数值, label = abs(负数值)), vjust = 1.5, size = 4) +
  geom_point(aes(y = Nb_diff * (max(正数值)/max(Nb_diff))), color = "#3498db", size = 3) +
  geom_richtext(aes(y = Nb_diff * (max(正数值)/max(Nb_diff)), label = Nb_diff),
                fill = "white", color = "#3498db", label.size = 0, size = 4) +
  scale_y_continuous(
    name = "正负数值",
    sec.axis = sec_axis(~ . / (max(df$正数值)/max(df$Nb_diff)), name = "Nb_diff差值")
  ) +
  labs(title = "月度正负数值与差值对比", x = "月份") +
  theme_minimal()

# 转为交互图
ggplotly(p)

内容的提问来源于stack exchange,提问作者ML_Enthousiast

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 01:29:53