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

如何在ggplot2中让负主轴对应的次轴条形图向上显示

解决ggplot2双轴图表中条形图向上显示的问题

我想用ggplot2创建双轴图表:主y轴为代表Log Odds的折线图(数值范围0至-8),次y轴为代表Weighted Count的条形图。当前条形图因主轴为负值向下显示,我需要它向上呈现——折线已正确从0向下到-8递减,但条形图需从主轴的-8刻度(对应次轴的0)开始,随计数增加向上延伸,二者共享同一基线。

我已尝试通过转换因子对齐两个刻度,将次轴数据基于主轴范围归一化并添加转换因子,但条形图仍从绘图区域顶部向下延伸,未达到预期效果。尝试的代码如下:

library(ggplot2)

# Sample data
set.seed(123)
bucket_label <- seq(0, 2.5, by=0.5)
log_odds <- seq(-1, -8, length.out=length(bucket_label))
Count <- sample(100:1000, length(bucket_label), replace = TRUE)
BucketedData_nonmat <- data.frame(bucket_label, log_odds)
Count.1 <- data.frame(bucket_label, Count)

# Current plot code
fit_range <- range(BucketedData_nonmat$log_odds, na.rm = TRUE)
freq_range <- range(Count.1$Count, na.rm = TRUE)
transformation_factor <- (freq_range[2] / fit_range[2]) /8

ggplot() +
  geom_bar(data = Count.1, aes(x = bucket_label, y = Count / transformation_factor), stat = "identity", fill = "grey", color = "grey", alpha = 0.2) +
  geom_line(data = BucketedData_nonmat, aes(x = bucket_label, y = log_odds), size = 1) +
  scale_y_continuous(
    name = "Log Odds",
    sec.axis = sec_axis(~ . * transformation_factor, name = "Weighted Count")
  )

解决方案

核心是将条形图的y值映射到主轴的[-8, 0]区间,让次轴的0对应主轴的-8,具体修正代码如下:

library(ggplot2)

# 样本数据
set.seed(123)
bucket_label <- seq(0, 2.5, by=0.5)
log_odds <- seq(-1, -8, length.out=length(bucket_label))
Count <- sample(100:1000, length(bucket_label), replace = TRUE)
BucketedData_nonmat <- data.frame(bucket_label, log_odds)
Count.1 <- data.frame(bucket_label, Count)

# 定义轴范围和转换因子
log_min <- -8  # 主轴基线,对应次轴计数0
log_max <- 0   # 主轴上限
count_max <- max(Count.1$Count)
# 转换因子:将计数映射到主轴的[-8,0]区间
trans_factor <- (log_max - log_min) / count_max

ggplot() +
  # 条形图:y值为基线(-8)加上计数对应的主轴偏移量
  geom_col(data = Count.1, aes(x = bucket_label, y = log_min + Count * trans_factor), 
           fill = "grey", color = "grey", alpha = 0.2) +
  # 折线图保持原数据
  geom_line(data = BucketedData_nonmat, aes(x = bucket_label, y = log_odds), size = 1) +
  scale_y_continuous(
    name = "Log Odds",
    # 设置主轴范围为0到-8,确保显示完整区间
    limits = c(log_min, log_max),
    sec.axis = sec_axis(
      # 次轴反向转换:从主轴y值得到计数
      ~ (. - log_min) / trans_factor,
      name = "Weighted Count"
    )
  ) +
  xlab("Bucket Label")

关键说明

  • geom_col的y值计算:log_min + Count * trans_factor,让计数为0时y=-8(基线),计数最大时y=0,条形从-8向上延伸;
  • scale_y_continuous的limits强制主轴显示0到-8的完整范围,保证基线对齐;
  • 次轴的转换公式把主轴的y值反向计算为计数,实现双轴刻度的准确对应。

调整后,折线从0向下到-8,条形从-8(次轴0)向上延伸,二者共享同一基线,符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 23:36:01