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

调整Secondary Axis匹配Primary Axis:实现次轴起始于0的方法

解决ggplot2次轴下限强制为0的问题

需求说明

  • 主轴(Avg. Asking Rate)始终使用自身数据的最小值作为下限
  • 次轴(Vacancy Rate)强制从0开始,不允许出现负值

问题根源

原代码的train_sec函数使用了次轴数据的完整范围(range(secondary))进行缩放转换,导致次轴下限会跟随原始数据的最小值变动,无法固定为0。

修改方案

调整次轴的缩放基准范围,强制将次轴的转换起始点设为0,而非原始数据的最小值。以下是修改后的完整代码:

library(dplyr)   
library(scales)  
library(ggplot2)

# 示例数据
stats <- data.frame(
  Snapshot.Date = as.Date(c("2020-09-30", "2020-12-31", "2021-03-31", "2021-06-30", "2021-09-30", "2021-12-31")),
  avg_asking_rate = c(
    4.93799293627304, 4.99132174488857, 4.97053998470495, 4.90321494004932,
    4.93494348159945, 4.91379691657121
  ),
  vacancy_rate = c(
    9.94185919399802, 11.5989188611645, 12.9308555110482, 13.9590437469142,
    13.5155036299108, 12.8472483323431
  )
)

# 修改后的次轴转换函数:强制次轴从0开始
train_sec <- function(primary, secondary, na.rm = TRUE) {
  # 次轴范围改为从0到最大值
  from <- c(0, max(secondary, na.rm = na.rm))
  to   <- range(primary, na.rm = na.rm)
  forward <- function(x) {
    rescale(x, from = from, to = to)
  }
  reverse <- function(x) {
    rescale(x, from = to, to = from)
  }
  list(fwd = forward, rev = reverse)
}

# 主轴下限取0.5的倍数(保持原逻辑)
y_lm <- floor((min(stats$avg_asking_rate))*2)/2

# 生成转换规则
sec <- with(stats, train_sec(stats$avg_asking_rate, stats$vacancy_rate))

# 绘图
stats %>%
  ggplot(., aes(x = `Snapshot.Date`, y = avg_asking_rate))+
  ggtitle("Rent") +
  geom_col(aes(fill = "Avg. Asking Rate"))+
  geom_line(aes(y = sec$fwd(vacancy_rate), colour =  "Vacancy Rate"), size = 1) +
  
  scale_x_date(name = NULL)+
  scale_y_continuous(name = "",
                     sec.axis = sec_axis(~sec$rev(.), name = "Vacancy Rate"))+
  coord_cartesian(ylim=c(y_lm,NA)) +
  scale_fill_manual(name = NULL, values = c("Avg. Asking Rate" = "blue", "Vacancy Rate" = "green"),
                    guide = guide_legend(order = 1))+
  scale_colour_manual(name = NULL, values = c("Vacancy Rate" = "green"), guide = guide_legend())

关键修改点

  • 在train_sec函数中,将次轴的缩放范围from从range(secondary)改为c(0, max(secondary, na.rm=na.rm)),强制次轴以0为下限
  • 主轴的下限逻辑保持不变,仍然基于自身数据最小值取0.5的倍数
  • 次轴的反向转换会自动基于新的范围生成,确保刻度从0开始

预期效果

预期输出效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 03:24:57