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

如何用R(ggplot2)或SAS绘制双独立轴游泳图:主轴随访时长,次轴日历时间

双独立轴游泳图的实现方案

R(ggplot2)实现

ggplot2原生对双独立轴支持有限,可通过将日期转换为数值变量,手动映射次轴刻度来实现需求,以下是完整流程:

数据预处理

扩展数据,增加日历时间的数值映射(以1950年为基准计算年份差):

library(dplyr)
library(ggplot2)

# 示例数据
data <- data.frame(
  ID = 1:10,
  start_date = as.Date(c('1950-01-01', '1960-02-01', '1970-03-01', '1980-04-01', '1990-05-01',
                         '1955-06-01', '1965-07-01', '1975-08-01', '1985-09-01', '1995-10-01')),
  end_date = as.Date(c('2000-01-01', '2010-02-01', '2020-03-01', '2015-04-01', '2025-05-01',
                       '1995-06-01', '2005-07-01', '2015-08-01', '2020-09-01', '2030-10-01'))
)

# 计算随访时长(年)和日历时间的数值映射
data <- data %>%
  mutate(
    follow_up_years = as.numeric(difftime(end_date, start_date, units = "weeks")) / 52.25,
    start_year = as.numeric(start_date - as.Date("1950-01-01")) / 365.25,
    end_year = as.numeric(end_date - as.Date("1950-01-01")) / 365.25
  )

绘图代码

# 定义日历轴的刻度与对应日期标签
calib_breaks <- seq(0, 80, 10)
calib_labels <- as.character(as.Date("1950-01-01") + calib_breaks*365.25)

ggplot(data, aes(y = factor(ID, levels = rev(1:10)))) +
  # 主轴:随访时长条形图(以x=0为起点)
  geom_bar(aes(x = follow_up_years), stat = "identity", fill = "#6366F1", width = 0.7) +
  # 次轴:日历时间起止线段
  geom_segment(aes(x = start_year, xend = end_year, yend = factor(ID, levels = rev(1:10))), 
               color = "#EF4444", size = 1.2) +
  # 添加起止点标记
  geom_point(aes(x = start_year), color = "#EF4444", size = 3) +
  geom_point(aes(x = end_year), color = "#EF4444", size = 3) +
  # 设置双轴
  scale_x_continuous(
    name = "随访时长(年)",
    sec.axis = sec_axis(
      trans = ~.,
      name = "日历时间",
      breaks = calib_breaks,
      labels = calib_labels
    )
  ) +
  ylab("研究对象ID") +
  theme_minimal() +
  theme(
    axis.title.x.bottom = element_text(color = "#6366F1"),
    axis.title.x.top = element_text(color = "#EF4444"),
    axis.text.x.top = element_text(angle = 45, hjust = 0)
  )

核心逻辑是将日期转换为与基准年的年份差,让日历时间数值与随访时长在同一x轴空间展示,再手动替换次轴刻度为日期格式,实现双独立轴效果。

SAS实现

SAS的PROC SGPLOT支持X2AXIS,同样通过日期转数值的方式实现需求:

数据预处理

/* 创建示例数据 */
data data;
  input ID start_date : date9. end_date : date9.;
  format start_date end_date date9.;
  /* 计算随访时长(年) */
  follow_up_years = (end_date - start_date) / 365.25;
  /* 计算日历时间的数值映射(以1950年1月1日为基准的年份) */
  start_year = (start_date - '01JAN1950'd) / 365.25;
  end_year = (end_date - '01JAN1950'd) / 365.25;
  datalines;
1 01JAN1950 01JAN2000
2 01FEB1960 01FEB2010
3 01MAR1970 01MAR2020
4 01APR1980 01APR2015
5 01MAY1990 01MAY2025
6 01JUN1955 01JUN1995
7 01JUL1965 01JUL2005
8 01AUG1975 01AUG2015
9 01SEP1985 01SEP2020
10 01OCT1995 01OCT2030
;
run;

绘图代码

proc sgplot data=data noautolegend;
  /* 主轴:随访时长条形图 */
  hbarparm category=ID response=follow_up_years / fillattrs=(color=#6366F1) barwidth=0.7;
  /* 次轴:日历时间线段和点 */
  highlow y=ID low=start_year high=end_year / type=bar lineattrs=(color=#EF4444 thickness=2);
  scatter y=ID x=start_year / markerattrs=(color=#EF4444 size=12);
  scatter y=ID x=end_year / markerattrs=(color=#EF4444 size=12);
  /* 设置X轴和X2轴 */
  xaxis label="随访时长(年)" valueattrs=(color=#6366F1);
  x2axis label="日历时间" 
         values=(0 to 80 by 10) 
         valueattrs=(color=#EF4444)
         tickvalueformat=(strip(put('01JAN1950'd + _VALUE_*365.25, date9.)));
  yaxis label="研究对象ID" reverse;
  styleattrs datacolors=(#6366F1 #EF4444);
run;

通过X2AXIS的tickvalueformat参数自定义刻度标签,将数值转换为日期格式,完成独立次轴的配置。

内容的提问来源于stack exchange,提问作者W. Fan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 06:47:09