geom_segment()时间数据的坐标轴刻度调整问题
问题:ggplot2绘制时间差线段图时x轴刻度设置失败
我有一个包含多时间点测量数据的数据集,记录了测量的预期时间(exp)与实际发生时间(act)。尝试用geom_segment()展示每个受试者的预期时间与实际时间的差异,但x轴刻度无法清晰读取,手动设置刻度时还出现报错。
报错代码及信息
> ggplot(df) + + geom_segment(aes(x = exp, xend = act, y = subject_id, yend = subject_id, color = timef)) + + scale_x_continuous(name = "diff. in time", + breaks = c("14:30", "15:00", "15:30","16:00", "16:30","17:00","17:30")) Error in `train_continuous()`: ! Discrete value supplied to a continuous scale > ggplot(df) + + geom_segment(aes(x = exp, xend = act, y = subject_id, yend = subject_id, color = timef)) + + scale_x_continuous(name = "diff. in time", + breaks = strptime(c("14:30", "15:00", "15:30","16:00", "16:30","17:00","17:30"), "%H:%M")) Error in `train_continuous()`: ! Discrete value supplied to a continuous scale Run `rlang::last_trace()` to see where the error occurred. > ggplot(df) + + geom_segment(aes(x = exp, xend = act, y = subject_id, yend = subject_id, color = timef)) + + scale_x_discrete(name = "diff. in time", + breaks = strptime(c("14:30", "15:00", "15:30","16:00", "16:30","17:00","17:30"), "%H:%M")) Error in `mapped_discrete()`: ! Can't convert `x` <list> to <double>. Run `rlang::last_trace()` to see where the error occurred
示例数据集
df <- structure(list(subject_id = c(102L, 166L, 123L, 152L, 173L, 151L, 138L, 155L, 183L, 148L, 139L, 141L, 112L, 123L, 179L, 166L, 150L, 183L, 155L, 172L), timef = c(5L, 5L, 10L, 2L, 2L, 2L, 3L, 7L, 3L, 4L, 6L, 4L, 6L, 2L, 10L, 4L, 3L, 8L, 10L, 3L), exp = c("16:08", "15:31", "17:28", "15:08", "15:02", "15:08", "15:51", "16:16", "15:32", "16:16", "15:58", "15:28", "16:31", "15:39", "16:34", "15:21", "15:08", "16:37", "17:16", "15:38"), act = c("16:11", "15:28", "17:28", "15:07", "15:02", "15:06", "15:51", "16:14", "15:32", "16:17", "15:58", "15:27", "16:29", "15:39", "16:34", "15:21", "15:08", "16:37", "17:16", "15:41")), row.names = c("102.1.5", "166.2.5", "123.2.10", "152.1.2", "173.1.2", "151.2.2", "138.2.3", "155.1.7", "183.1.3", "148.2.4", "139.2.6", "141.2.4", "112.2.6", "123.1.2", "179.2.10", "166.1.4", "150.1.3", "183.1.8", "155.1.10", "172.1.3"), class = "data.frame")
解决方案
核心问题是你的exp和act列是字符类型,但错误使用了连续型/离散型比例尺处理时间数据。正确做法是先将时间列转换为时间类型,再用对应时间比例尺设置刻度。
方法1:用hms包处理纯时间格式
hms包专门适配小时:分钟格式的时间,ggplot支持良好:
library(ggplot2) library(hms) # 转换时间列为hms类型 df$exp <- parse_hms(df$exp) df$act <- parse_hms(df$act) # 绘制图表并设置自定义刻度 ggplot(df) + geom_segment(aes(x = exp, xend = act, y = subject_id, yend = subject_id, color = timef)) + scale_x_time( name = "时间", breaks = parse_hms(c("14:30", "15:00", "15:30","16:00", "16:30","17:00","17:30")), labels = format(parse_hms(c("14:30", "15:00", "15:30","16:00", "16:30","17:00","17:30")), "%H:%M") ) + labs(y = "受试者ID", color = "时间组")
方法2:转换为POSIXct类型(带日期)
如果需要保留日期维度(可指定任意基础日期,仅用时间部分):
library(ggplot2) # 转换为POSIXct类型,指定基础日期 df$exp <- as.POSIXct(paste("2024-01-01", df$exp), format = "%Y-%m-%d %H:%M") df$act <- as.POSIXct(paste("2024-01-01", df$act), format = "%Y-%m-%d %H:%M") # 定义刻度断点 break_times <- as.POSIXct(paste("2024-01-01", c("14:30", "15:00", "15:30","16:00", "16:30","17:00","17:30")), format = "%Y-%m-%d %H:%M") ggplot(df) + geom_segment(aes(x = exp, xend = act, y = subject_id, yend = subject_id, color = timef)) + scale_x_datetime( name = "时间", breaks = break_times, labels = format(break_times, "%H:%M"), # 仅显示小时:分钟 date_labels = "%H:%M" ) + labs(y = "受试者ID", color = "时间组")
额外优化:自动减少刻度数量
无需手动指定所有断点,可用date_breaks自动设置间隔:
# 以hms类型为例 ggplot(df) + geom_segment(aes(x = exp, xend = act, y = subject_id, yend = subject_id, color = timef)) + scale_x_time( name = "时间", date_breaks = "30 mins", # 每30分钟一个刻度 date_labels = "%H:%M" )
内容的提问来源于stack exchange,提问作者Mia
相关产品推荐
相关产品推荐

