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

如何筛选处于多个治疗时间区间内的评分数据(R语言)

问题描述

需要从数据框中筛选出**评分时间(score_time)**处于对应ID的任意治疗时间区间内的评分记录。每个ID包含多条带测量时间的评分数据,以及多条治疗开始(treatment_start)和结束(treatment_end)时间记录。

数据结构如下:

structure(list(ID = c("A", "A", "A", "A", "A", "B", "B", "B", 
"B", "B"), score_time = c("2022/09/01 9:00:00", "2022/09/02 18:00:00", 
"2022/09/03 12:00:00", NA, NA, "2022/09/15 18:00:00", "2022/09/18 20:00:00", 
NA, NA, NA), score = c(243, 232, 319, NA, NA, 436, 310, NA, NA, 
NA), treatment_start = c(NA, NA, NA, "2022/09/02 8:00:00", "2022/09/03 11:00:00", 
NA, NA, "2022/09/15 8:00:00", "2022/09/16 14:00:00", "2022/09/16 23:00:00" 
), treatment_end = c(NA, NA, NA, "2022/09/02 22:00:00", "2022/09/09 12:00:00", 
NA, NA, "2022/09/16 2:00:00", "2022/09/16 22:00:00", "2022/09/17 0:00:00" 
)), row.names = c(NA, -10L), spec = structure(list(cols = list(
    ID = structure(list(), class = c("collector_character", "collector"
    )), score_time = structure(list(), class = c("collector_character", 
    "collector")), score = structure(list(), class = c("collector_double", 
    "collector")), treatment_start = structure(list(), class = c("collector_character", 
    "collector")), treatment_end = structure(list(), class = c("collector_character", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
"collector")), delim = ","), class = "col_spec"), problems = <pointer: 0x6000000190b0>, class = c("spec_tbl_df", 
"tbl_df", "tbl", "data.frame"))

表格预览:

IDscore_timescoretreatment_starttreatment_end
A2022/09/01 9:00:00243NANA
A2022/09/02 18:00:00232NANA
A2022/09/03 12:00:00319NANA
ANANA2022/09/02 8:00:002022/09/02 22:00:00
ANANA2022/09/03 11:00:002022/09/09 12:00:00
B2022/09/15 18:00:00436NANA
B2022/09/18 20:00:00310NANA
BNANA2022/09/15 8:00:002022/09/16 2:00:00
BNANA2022/09/16 14:00:002022/09/16 22:00:00
BNANA2022/09/16 23:00:002022/09/17 0:00:00

目标输出(排除不在治疗区间的评分):

# A tibble: 3 × 2
  ID    score
  <chr> <dbl>
1 A       232
2 A       319
3 B       436

此前尝试的宽表转换方法无法正确匹配时间区间,需要更高效的合并与匹配方案。


解决方案

核心思路是拆分评分数据与治疗区间数据,按ID交叉匹配后筛选符合条件的记录,使用tidyverse+lubridate实现:

library(tidyverse)
library(lubridate)

# 1. 拆分并清洗数据
# 提取有效评分记录,转换时间格式
score_data <- data %>%
  filter(!is.na(score_time)) %>%
  mutate(score_time = ymd_hms(score_time)) %>%
  select(ID, score_time, score)

# 提取有效治疗区间记录,转换时间格式并生成区间对象
treatment_data <- data %>%
  filter(!is.na(treatment_start)) %>%
  mutate(
    treatment_start = ymd_hms(treatment_start),
    treatment_end = ymd_hms(treatment_end),
    trt_interval = interval(treatment_start, treatment_end)
  ) %>%
  select(ID, trt_interval)

# 2. 交叉匹配并筛选结果
result <- score_data %>%
  inner_join(treatment_data, by = "ID") %>%
  filter(score_time %within% trt_interval) %>%
  distinct(ID, score) %>%  # 去除同一评分匹配多个区间的重复行
  arrange(ID)

# 输出结果
result

代码解释
  1. 数据拆分与清洗

    • 从原始数据中分离出无NA的评分记录和治疗区间记录,避免无效数据干扰
    • 用ymd_hms()将字符型时间转换为lubridate可识别的时间格式,为后续区间匹配做准备
  2. 交叉匹配与筛选

    • 通过inner_join()按ID将评分数据与治疗区间数据全连接,让每条评分记录对应同一个ID的所有治疗区间
    • 使用lubridate的%within%运算符直接判断评分时间是否落在某个治疗区间内
  3. 结果整理

    • 用distinct()去除同一评分匹配多个区间产生的重复行
    • 按ID排序得到最终的目标结果

该方案逻辑清晰,避免了宽表转换的复杂操作,在多ID多区间的场景下效率更高。

内容的提问来源于stack exchange,提问作者KintensT

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 05:00:53