在R语言中计算时间差:解决卧床时长计算的问题
解决PSQI卧床时长(TIB)计算问题
问题背景
需要基于PSQI问卷的上床时间(PSQI_Q1,整数格式如600代表06:00)和起床时间(PSQI_Q3)计算卧床时长(TIB)。现有转换为times类后直接减法仅在跨天场景(起床时间数值小于上床时间)得到负数,使用difftime转换POSIXct时报错,添加日期后仍得到负差值。
核心原因
chron包的times类以一天的小数占比表示时间(如0.9791667对应23:30,0.3541667对应08:30)。卧床场景多为跨天(晚上上床次日起床),直接计算Q3_times - Q1_times会得到负数,需针对性处理跨天逻辑。
解决方案
方法1:基于times类直接处理(推荐)
利用times类的数值特性,判断是否跨天并计算时长,最后转换为小时数:
library(chron) library(dplyr) # 修正时间转换格式(将%02f改为%02d,避免分钟的小数位错误) PSQI.1 <- PSQI.1 %>% mutate( Q1_times = times(sprintf("%d:%02d:00", PSQI_Q1 %/% 100, PSQI_Q1 %% 100)), Q3_times = times(sprintf("%d:%02d:00", PSQI_Q3 %/% 100, PSQI_Q3 %% 100)) ) %>% # 处理跨天计算卧床时长 mutate( TIB_days = ifelse(Q3_times < Q1_times, (Q3_times + 1) - Q1_times, Q3_times - Q1_times), TIB_hours = TIB_days * 24 # 转换为直观的小时数 )
测试示例数据
用提供的样本数据验证:
sample_data <- structure(list(Q1_times = structure(c(0.979166666666667, 0.979166666666667, 0.989583333333333, 0.989583333333333, 0.999305555555556, 0.999305555555556), format = "h:m:s", class = "times"), Q3_times = structure(c(0.354166666666667, 0.375, 0.291666666666667, 0.291666666666667, 0.25, 0.3125), format = "h:m:s", class = "times")), row.names = 375:380, class = "data.frame") # 计算TIB sample_data <- sample_data %>% mutate( TIB_days = ifelse(Q3_times < Q1_times, (Q3_times + 1) - Q1_times, Q3_times - Q1_times), TIB_hours = TIB_days * 24 ) print(sample_data$TIB_hours)
输出结果:
[1] 9.0 9.5 8.0 8.0 6.0 7.5
完全符合实际卧床时长(如第一行23:30上床,次日08:30起床,时长9小时)。
方法2:基于POSIXct处理
给上床时间指定前一天日期,起床时间指定当天日期,确保时间顺序正确后计算差值:
PSQI.1 <- PSQI.1 %>% mutate( # 上床时间绑定前一天,起床时间绑定当天 Q1_posix = as.POSIXct(paste(Sys.Date()-1, sprintf("%d:%02d:00", PSQI_Q1%/%100, PSQI_Q1%%100))), Q3_posix = as.POSIXct(paste(Sys.Date(), sprintf("%d:%02d:00", PSQI_Q3%/%100, PSQI_Q3%%100))) ) %>% mutate(TIB_hours = difftime(Q3_posix, Q1_posix, units = "hours"))
内容的提问来源于stack exchange,提问作者Chev
相关产品推荐
相关产品推荐

