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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 16:14:50