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

R语言ggplot2同图绘制二值与数值变量的y轴刻度问题

问题核心原因

不同量纲、不同取值范围的变量共用单一Y轴会导致刻度适配错误:数据中SID取值范围为301~358,二值变量Lowt、Hit仅取0/1,强行映射到同一Y轴时会出现其中一类变量无法正常显示的问题。
异常绘图示例

首先做数据预处理,把时间字符串转为标准时间格式,保证X轴按时间顺序展示:

library(ggplot2)
library(dplyr)
library(lubridate)
library(tidyr)

dat <- structure(list(timestamp = c("29-06-2021-06:00", "29-06-2021-06:01", 
"29-06-2021-06:02", "29-06-2021-06:03", "29-06-2021-06:04", "29-06-2021-06:05", 
"29-06-2021-06:06", "29-06-2021-06:07", "29-06-2021-06:08", "29-06-2021-06:09", 
"29-06-2021-06:10", "29-06-2021-06:11", "29-06-2021-06:12", "29-06-2021-06:13", 
"29-06-2021-06:14", "29-06-2021-06:15", "29-06-2021-06:16", "29-06-2021-06:17", 
"29-06-2021-06:18", "29-06-2021-06:19", "29-06-2021-06:20", "29-06-2021-06:21", 
"29-06-2021-06:22", "29-06-2021-06:23", "29-06-2021-06:24", "29-06-2021-06:25", 
"29-06-2021-06:26"), SID = c(301L, 351L, 304L, 357L, 358L, 302L, 
303L, 309L, 356L, 304L, 308L, 351L, 304L, 357L, 358L, 302L, 303L, 
352L, 307L, 353L, 304L, 308L, 352L, 307L, 304L, 354L, 356L), 
    Tor = c(0.70161919, 0.639416295, 0.288282073, 0.932362166, 
    0.368616626, 0.42175565, 0.409735918, 0.942170196, 0.381396521, 
    0.818102394, 0.659391671, 0.246387978, 0.196001777, 0.632630259, 
    0.66618385, 0.440625167, 0.639759498, 0.050001835, 0.775660271, 
    0.762934189, 0.516830196, 0.244674975, 0.38620466, 0.970792903, 
    0.752674581, 0.190366737, 0.56596405), Lowt = c(0L, 0L, 1L, 
    0L, 1L, 0L, 1L, 0L, 1L, 0L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 1L, 
    0L, 0L, 0L, 1L, 1L, 0L, 0L, 1L, 0L), Hit = c(1L, 0L, 0L, 
    1L, 0L, 0L, 0L, 1L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    1L, 1L, 0L, 0L, 0L, 1L, 1L, 0L, 0L)), class = "data.frame", row.names = c(NA, 
-27L))

# 转换时间戳格式
dat <- dat %>%
  mutate(timestamp = dmy_hm(timestamp))
可行解决方案

方案1:双Y轴同画布展示

通过线性缩放将0-1区间的二值变量映射到SID的取值范围,同时在右侧添加对应0-1刻度的副轴,实现两类变量同图展示:

# 计算缩放参数
sid_range <- range(dat$SID)
scale_val <- sid_range[2] - sid_range[1]

ggplot(dat, aes(x = timestamp)) +
  geom_line(aes(y = SID, color = "SID"), linewidth = 1) +
  geom_point(aes(y = Lowt * scale_val + sid_range[1], color = "Lowt", shape = "Lowt"), size = 3) +
  geom_point(aes(y = Hit * scale_val + sid_range[1], color = "Hit", shape = "Hit"), size = 3) +
  # 配置双Y轴
  scale_y_continuous(
    name = "SID取值",
    sec.axis = sec_axis(~ (. - sid_range[1])/scale_val, name = "二值变量取值", breaks = c(0, 1))
  ) +
  scale_color_manual(values = c("SID" = "#1f77b4", "Lowt" = "#ff7f0e", "Hit" = "#2ca02c")) +
  scale_shape_manual(values = c("Lowt" = 16, "Hit" = 17)) +
  labs(x = "时间", color = "变量", shape = "变量") +
  theme_bw()

注意:原代码中new_1、Timestamp为对象/列名笔误,运行前需和实际数据集的命名统一。

方案2:分面堆叠展示(更推荐)

双Y轴容易产生视觉误导,正式分析场景优先选择分面方案,每个变量使用独立Y轴,不存在量纲冲突,可读性更强:

# 转换为长格式适配分面
dat_long <- dat %>%
  select(timestamp, SID, Lowt, Hit) %>%
  pivot_longer(cols = -timestamp, names_to = "var", values_to = "value")

ggplot(dat_long, aes(x = timestamp, y = value)) +
  geom_line(data = ~filter(.x, var == "SID"), color = "#1f77b4", linewidth = 1) +
  geom_point(data = ~filter(.x, var != "SID"), aes(color = var), size = 2.5) +
  facet_wrap(~var, ncol = 1, scales = "free_y") +
  scale_x_datetime(date_labels = "%H:%M") +
  labs(x = "时间", y = "取值", color = "二值变量") +
  theme_bw()
  • 若必须将所有元素叠加在同一坐标区,选择方案1,需要明确标注左右轴对应的变量,避免误读
  • 若用于报告、论文等正式场景,选择方案2,刻度逻辑清晰,无视觉误导

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 10:27:24