R语言中按患者内日期降序排序计算TIB的列表问题
解决卧床时间(TIB)计算中的排序错位问题
处理包含患者上床时间(inbed)和下床时间(uitbed)的数据集计算卧床时间(TIB)时,小型测试数据集(<10天)运行正常,但超过10天的数据集因列表排序错误,导致TIB值粘贴到表格对应行时错位。当前SDa_day按字符串字典序排序(如SDa1.1, SDa10.1, SDa11.1),交换分组顺序后排序为1 SDa1, 2 SDa1, 3 SDa1,均不符合**按患者分组,再按SDa_day数字升序(示例:1 SDa1, 1 SDa2, 1 SDa3)**的需求。
示例数据
acti_sd <- data.frame( patient = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), diagnosis = c(1, 1, 4, 5, 4, 1, 2, 2, 5, 3, 4), SDa1_inbed = c("19:00", "20:00", "18:30", "23:00", "20:00", "20:00", "20:00", "18:30", "20:00", "18:30", "20:00"), SDa2_inbed = c("01:00", "00:00", "23:25", "00:00", "22:45", "00:15", "00:00", "23:25", "00:00", "23:25", "00:00"), SDa1_uitbed = c("06:15", "10:00", "09:00", "08:00", "99:99", "06:15", "10:00", "09:00", "10:00", "09:00", "10:00"), SDa2_uitbed = c("09:30", "04:00", "08:30", "05:00", "06:30", "07:45", "04:00", "08:30", "04:00", "08:30", "04:00") )
现有数据处理与TIB计算代码
NA处理与格式转换
acti_sd[acti_sd == '99:99'] <- NA long_actisd <- acti_sd %>% pivot_longer(cols = !c(patient, diagnosis), names_to = c("SDa_day", "measurementtype"), names_sep = "_", values_to = "measurement" ) long_wide_actisd <- long_actisd %>% pivot_wider(names_from = "measurementtype", values_from = "measurement")
TIB计算函数与分组处理
# TIB计算函数 calc_TIB <- function(inbed, uitbed) { in_bed_time <- as.numeric(as.POSIXct(inbed, format = "%H:%M")) out_bed_time <- as.numeric(as.POSIXct(uitbed, format = "%H:%M")) # 处理跨午夜的情况 out_bed_time <- ifelse(out_bed_time < in_bed_time, out_bed_time + 86400, out_bed_time) # 转换为小时 tib <- (out_bed_time - in_bed_time) / 3600 return(tib) } # 按日期和患者分组计算TIB result <- lapply(split(long_wide_actisd[, c("inbed", "uitbed")], list(long_wide_actisd$SDa_day, long_wide_actisd$patient)), function(x)calc_TIB(x$inbed, x$uitbed)) # 转换为矩阵并合并到原表 SDa_TIB <- do.call(rbind, result) long_wide_actisd <- cbind(long_wide_actisd, SDa_TIB) print(long_wide_actisd)
问题核心
SDa_day是字符串类型(如SDa1, SDa10),分组时会按字符串字典序排序,导致SDa10排在SDa2之前,最终TIB结果与原表行顺序不匹配。
解决方案
步骤1:提取SDa_day的数值部分
在格式转换后,从SDa_day中提取数字并转为数值型,避免字符串排序干扰:
library(stringr) long_wide_actisd <- long_wide_actisd %>% mutate(SDa_day_num = as.numeric(str_extract(SDa_day, "\\d+")))
步骤2:按患者+SDa_day数字排序原表
确保原表行顺序与后续计算顺序一致:
long_wide_actisd <- long_wide_actisd %>% arrange(patient, SDa_day_num) # 若需降序则改为arrange(patient, desc(SDa_day_num))
步骤3:按正确顺序分组计算TIB
调整分组顺序为patient在前、SDa_day_num在后,保证分组逻辑与排序一致:
result <- lapply(split(long_wide_actisd[, c("inbed", "uitbed")], list(long_wide_actisd$patient, long_wide_actisd$SDa_day_num)), function(x)calc_TIB(x$inbed, x$uitbed)) SDa_TIB <- do.call(rbind, result) long_wide_actisd$SDa_TIB <- SDa_TIB
更简洁的优化方案:用dplyr直接分组计算
无需手动处理分组和排序,dplyr会自动保证结果与原表行顺序匹配:
long_wide_actisd <- long_wide_actisd %>% group_by(patient, SDa_day_num) %>% mutate(SDa_TIB = calc_TIB(inbed, uitbed)) %>% ungroup()
以上方法可彻底解决字符串排序导致的TIB值错位问题,无论数据集天数多少,都能保证结果与患者、日期正确对应。
内容的提问来源于stack exchange,提问作者froggishrock
相关产品推荐
相关产品推荐

