使用scales::label_time时X轴天数计数未从0开始的优化方案咨询
温度随时间变化绘图的X轴优化方案
我有一个用于跟踪温度随时间变化的表格d_raw,计划使用lubridate整理数据后进行绘图。但遇到X轴未从0开始计数的问题,目前通过labels = function(x) {paste(hms(x)/days(1))}临时解决,但该方法不够优雅,希望能得到改进脚本的建议。
原始代码与问题
library(tidyverse) d_raw <- tibble( Time = c("2023-02-01 14:00", "2023-02-02 12:00", "2023-02-03 13:00", "2023-02-04 14:00", "2023-02-05 15:00"), Temperature = c(25,18,20,19,32) ) Tzero <- ymd_hm("2023-02-01 8:00") d <- d_raw |> mutate(Time = ymd_hm(Time), spent = interval(Tzero, Time)) d #> # A tibble: 5 × 3 #> Time Temperature spent #> <dttm> <dbl> <Interval> #> 1 2023-02-01 14:00:00 25 2023-02-01 08:00:00 UTC--2023-02-01 14:00:00 UTC #> 2 2023-02-02 12:00:00 18 2023-02-01 08:00:00 UTC--2023-02-02 12:00:00 UTC #> 3 2023-02-03 13:00:00 20 2023-02-01 08:00:00 UTC--2023-02-03 13:00:00 UTC #> 4 2023-02-04 14:00:00 19 2023-02-01 08:00:00 UTC--2023-02-04 14:00:00 UTC #> 5 2023-02-05 15:00:00 32 2023-02-01 08:00:00 UTC--2023-02-05 15:00:00 UTC
尝试直接绘图时,用scale_x_time设置X轴从0开始,标签显示天数,但结果不符合预期:
p <- ggplot(d, aes(x = spent, y = Temperature)) + geom_point() + geom_line() + xlab("Time spent (d)") + ylim(c(0, NA)) p + scale_x_time(limits = c(0,NA), breaks = scales::breaks_width("2 days"), labels = scales::label_time("%d"))

临时解决方法虽然能显示正确的天数,但会出现解析警告,且代码不够简洁:
p + scale_x_time(limits = c(0,NA), breaks = scales::breaks_width("2 days"), labels = function(x) {paste(hms(x)/days(1))}) #> Warning in .parse_hms(..., order = "HMS", quiet = quiet): Some strings failed #> to parse, or all strings are NAs

改进方案
核心问题是用interval类型作为X轴变量不太适合数值化的时间差展示,直接计算从Tzero到每个时间点的**天数差(数值型)**会更直观,也能避免类型转换的问题。
步骤1:重新整理数据
将spent字段改为计算时间差的数值,用difftime转换为天数:
d <- d_raw |> mutate(Time = ymd_hm(Time), # 直接计算与Tzero的天数差,保留小数精度 spent_days = as.numeric(difftime(Time, Tzero, units = "days")))
整理后的数据:
d #> # A tibble: 5 × 3 #> Time Temperature spent_days #> <dttm> <dbl> <dbl> #> 1 2023-02-01 14:00:00 25 0.25 #> 2 2023-02-02 12:00:00 18 1.167 #> 3 2023-02-03 13:00:00 20 2.208 #> 4 2023-02-04 14:00:00 19 3.25 #> 5 2023-02-05 15:00:00 32 4.292
步骤2:绘图优化
现在X轴是数值型,直接用scale_x_continuous设置刻度和标签,代码简洁无警告:
ggplot(d, aes(x = spent_days, y = Temperature)) + geom_point() + geom_line() + xlab("Time spent (d)") + ylim(c(0, NA)) + scale_x_continuous( limits = c(0, NA), breaks = scales::breaks_width(2), # 每2天设置一个刻度 labels = scales::label_number(accuracy = 0.1) # 按需调整小数精度 )
这样绘制的图X轴从0开始,天数显示准确,完全满足需求。
内容的提问来源于stack exchange,提问作者Midoux
相关产品推荐
相关产品推荐

