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

R语言ggplot坐标轴断点设置及图例合并方法求助

住院时长数据可视化优化方案

问题背景与数据

我用R处理患者住院时长数据,其中9999-12-31代表患者仍在住院(用三角形标识),每个患者有多条住院记录,数据如下:

df = structure(list(var1 = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
2L, 3L, 3L, 3L, 3L, 2L), .Label = c("A", "B", "C"), class = "factor"), 
    start_date = structure(c(18169, 18217, 17933, 16232, 15901, 
    18692, 17548, 16848, 19077, 16959, 16974, 16744, 19358), class = "Date"), 
    end_date = structure(c(19189, 18217, 18392, 17372, 18501, 
    18692, 17548, 16848, 19077, 16959, 17777, 17126, 2932896), class = "Date")), row.names = c(NA, 
-13L), class = "data.frame")

现有可视化代码

我尝试绘制每条住院记录的时长图表,代码如下:

# 补充原代码缺失的列定义
df$row <- seq(nrow(df))
df$hospital_patient <- df$var1
palette <- c("A" = "red", "B" = "blue", "C" = "green")

p <- ggplot(df, aes(x = start_date, xend = end_date, y = row, yend = row, color = hospital_patient)) +
  geom_segment(size = 1.5, lineend = "round") +
  geom_point(aes(x = start_date), size = 3) +
  geom_point(data = df[df$end_date != as.Date('9999-12-31'),], aes(x = end_date), size = 3) +
  geom_point(data = df[df$end_date == as.Date('9999-12-31'),], aes(x = end_date), size = 3, shape = 17) +
  scale_color_manual(values = palette) +
  labs(x = "Time", y = "Row") +
  theme_minimal()

p <- p + geom_vline(aes(xintercept = as.numeric(Sys.Date()), linetype = "Today"), color = "black", size = 1.5)
p + scale_linetype_manual(values = c("Today" = "dotted"))

待解决问题

  • 目前只能手动将9999-12-31替换为未来日期(如2030-12-31)再修改轴标签,否则图表会因日期范围过大变形,能否用坐标轴断点实现需求?
  • 如何将患者(颜色)图例与“今日”竖线(线型)图例合并为一个统一图例?

解决方案

1. 用坐标轴断点处理9999-12-31日期

ggplot2本身不支持坐标轴断点,可借助ggbreak包实现。核心思路是把x轴拆分为两段:一段是实际住院日期的正常范围,另一段单独放置9999-12-31的标记,无需修改原始日期。

示例代码:

library(ggbreak)

# 确定实际日期的最大范围(排除9999-12-31)
max_real_date <- max(df$end_date[df$end_date != as.Date("9999-12-31")])
# 设置断点位置,在实际最大日期后留两年间隔
break_pos <- max_real_date + 365*2

p_break <- ggplot(df, aes(x = start_date, xend = end_date, y = row, yend = row, color = hospital_patient)) +
  geom_segment(size = 1.5, lineend = "round") +
  geom_point(aes(x = start_date), size = 3) +
  geom_point(data = df[df$end_date != as.Date('9999-12-31'),], aes(x = end_date), size = 3) +
  geom_point(data = df[df$end_date == as.Date('9999-12-31'),], aes(x = end_date), size = 3, shape = 17) +
  scale_color_manual(values = palette) +
  geom_vline(aes(xintercept = as.numeric(Sys.Date()), linetype = "Today"), color = "black", size = 1.5) +
  scale_linetype_manual(values = c("Today" = "dotted")) +
  # 设置x轴断点,自定义标签
  scale_x_date_break(breaks = break_pos, 
                     labels = function(x) {
                       ifelse(x == as.Date("9999-12-31"), "9999", format(x, "%Y"))
                     },
                     expand = c(0, 0)) +
  labs(x = "Time", y = "Row") +
  theme_minimal()

p_break

2. 合并患者与“今日”竖线图例

要合并两个不同美学(颜色、线型)的图例,需要统一图例名称,并通过guide_legend()手动调整图例元素,让两个类别在同一个图例中展示。

示例代码:

p_combined <- ggplot(df, aes(x = start_date, xend = end_date, y = row, yend = row, color = hospital_patient)) +
  geom_segment(size = 1.5, lineend = "round") +
  geom_point(aes(x = start_date), size = 3) +
  geom_point(data = df[df$end_date != as.Date('9999-12-31'),], aes(x = end_date), size = 3) +
  geom_point(data = df[df$end_date == as.Date('9999-12-31'),], aes(x = end_date), size = 3, shape = 17) +
  # 把"Today"加入颜色映射,设置颜色为黑色
  scale_color_manual(values = c(palette, "Today" = "black"),
                     labels = c("A", "B", "C", "Today")) +
  # 竖线同时映射color和linetype为"Today"
  geom_vline(aes(xintercept = as.numeric(Sys.Date()), color = "Today", linetype = "Today"), size = 1.5) +
  scale_linetype_manual(values = c("Today" = "dotted")) +
  # 合并图例,自定义每个条目的显示样式
  guides(color = guide_legend(override.aes = list(
    linetype = c("solid", "solid", "solid", "dotted"),
    shape = c(19, 19, 19, NA),
    size = c(1.5, 1.5, 1.5, 1.5)
  )),
  linetype = "none") +  # 隐藏单独的线型图例
  labs(x = "Time", y = "Row", color = "Legend") +
  theme_minimal()

p_combined

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:48:12