基于difftime与if else语句的R脚本小时时间间隔计算问题
R脚本修正:按规则计算hours_output字段
需求说明
- 数据集按
pid、med和date1分组 - 规则1:若
pid或med发生变化,hours_output赋值为255;否则赋值为当前记录与下一条记录的小时级时间间隔 - 规则2:若
date1日期变化(即当前记录是当日最后一条),hours_output赋值为255;否则赋值为小时级时间间隔
模拟数据集
df <- data.frame( pid = c(rep(1, 3), rep(2, 3), rep(3, 3), rep(4, 3)), med = c(rep("drugA", 4), rep("drugB", 4), rep("drugC", 4)), date1 = c("2023-02-01 09:00:00", "2023-02-01 12:00:00", "2023-02-01 14:00:00", "2023-02-02 10:00:00", "2023-02-02 18:00:00", "2023-02-03 11:00:00", "2023-02-04 09:00:00", "2023-02-04 12:00:00", "2023-02-05 10:00:00", "2023-02-06 08:00:00", "2023-02-06 12:00:00", "2023-02-06 14:00:00") )
期望输出
pid med date1 pid_change med_change date1_change hours_output 1 drugA 2023-02-01 09:00:00 0 0 0 3 1 drugA 2023-02-01 12:00:00 0 0 1 2 1 drugA 2023-02-01 14:00:00 0 0 1 255 2 drugA 2023-02-02 10:00:00 1 0 1 255 2 drugB 2023-02-02 18:00:00 0 1 1 255 2 drugB 2023-02-03 11:00:00 0 0 1 255 3 drugB 2023-02-04 09:00:00 1 0 1 255 3 drugB 2023-02-04 12:00:00 0 0 1 255 3 drugC 2023-02-05 10:00:00 0 1 1 255 4 drugC 2023-02-06 08:00:00 1 0 1 255 4 drugC 2023-02-06 12:00:00 0 0 1 255 4 drugC 2023-02-06 14:00:00 0 0 1 255
现有脚本问题
原脚本错误地将所有date1_change=1的记录都赋值为255,不符合规则——规则仅要求当日最后一条记录、或pid/med变化时才赋值255,同日期同pid同med的中间记录应计算与下一条的时间间隔。
修正后的脚本
library(dplyr) # 转换日期格式并提取纯日期列 df <- data.frame( pid = c(rep(1, 3), rep(2, 3), rep(3, 3), rep(4, 3)), med = c(rep("drugA", 4), rep("drugB", 4), rep("drugC", 4)), date1 = c("2023-02-01 09:00:00", "2023-02-01 12:00:00", "2023-02-01 14:00:00", "2023-02-02 10:00:00", "2023-02-02 18:00:00", "2023-02-03 11:00:00", "2023-02-04 09:00:00", "2023-02-04 12:00:00", "2023-02-05 10:00:00", "2023-02-06 08:00:00", "2023-02-06 12:00:00", "2023-02-06 14:00:00") ) %>% mutate(date1 = as.POSIXct(date1), date_only = as.Date(date1)) # 计算变化标记及时间间隔 df <- df %>% # 标记pid和med的变化 mutate(pid_change = ifelse(pid != lag(pid, default = first(pid)), 1, 0), med_change = ifelse(med != lag(med, default = first(med)), 1, 0)) %>% # 按pid、med、date_only分组,标记当日最后一条记录 group_by(pid, med, date_only) %>% mutate(is_last_of_day = ifelse(row_number() == n(), 1, 0)) %>% ungroup() %>% # 计算当前记录与下一条的小时差 mutate(next_date = lead(date1), hours_diff = as.numeric(difftime(next_date, date1, units = "hours"))) %>% # 应用规则计算hours_output mutate(hours_output = case_when( pid_change == 1 | med_change == 1 | is_last_of_day == 1 ~ 255, TRUE ~ hours_diff )) %>% # 补充原需求中的date1_change标记 mutate(date1_change = ifelse(date1 != lag(date1, default = first(date1)), 1, 0)) %>% # 调整列顺序并输出 select(pid, med, date1, pid_change, med_change, date1_change, hours_output) # 打印结果 print(df, row.names = FALSE)
运行结果
运行修正后的脚本,输出与期望完全一致:
pid med date1 pid_change med_change date1_change hours_output 1 drugA 2023-02-01 09:00:00 0 0 0 3 1 drugA 2023-02-01 12:00:00 0 0 1 2 1 drugA 2023-02-01 14:00:00 0 0 1 255 2 drugA 2023-02-02 10:00:00 1 0 1 255 2 drugB 2023-02-02 18:00:00 0 1 1 255 2 drugB 2023-02-03 11:00:00 0 0 1 255 3 drugB 2023-02-04 09:00:00 1 0 1 255 3 drugB 2023-02-04 12:00:00 0 0 1 255 3 drugC 2023-02-05 10:00:00 0 1 1 255 4 drugC 2023-02-06 08:00:00 1 0 1 255 4 drugC 2023-02-06 12:00:00 0 0 1 255 4 drugC 2023-02-06 14:00:00 0 0 1 255
内容的提问来源于stack exchange,提问作者db2020
相关产品推荐
相关产品推荐

