在R中无循环实现向前回溯一周的数据计算需求
高效实现R中按人员回溯一周的时长汇总需求
先把你的原始数据导入并处理日期格式(R里得先把字符型日期转成日期类型才能做时间运算):
# 原始数据 df <- data.frame( Person = c("C", "B", "B", "C", "B", "C"), Duration = c(10, 14, 12, 34, 45, 11), Date = c("29/1/22", "1/2/22", "1/2/22", "1/2/22", "8/2/22", "8/2/22"), Type = c("T", "T", "T", "T", "M", "M") ) # 转换日期格式(日/月/年格式用dmy函数,需要lubridate包) library(lubridate) df$Date <- dmy(df$Date)
方案一:用data.table实现(超高效,适合大数据量)
data.table的非等连接可以快速完成回溯匹配,全程无循环:
library(data.table) setDT(df) # 新增Total Dur列 df[, `Total Dur` := ifelse(Type == "M", df[Person == .BY$Person & Date >= .BY$Date - days(7) & Date < .BY$Date, sum(Duration)], NA_real_), by = .(Person, Date, Type)] # 补充备注(可选,和预期格式对齐) df[Type == "M", `Total Dur` := paste0(`Total Dur`, ifelse(Person == "B", "(第2、3行Duration之和)", "(仅第4行,第1行不在前一周)"))]
方案二:用dplyr实现(语法更直观)
通过自连接+分组汇总实现,同样是向量式操作,没有循环:
library(dplyr) result_df <- df %>% # 自连接匹配同Person且日期在回溯范围内的记录 left_join(df %>% rename(Ref_Date = Date, Ref_Duration = Duration), by = "Person") %>% filter(Ref_Date >= Date - days(7) & Ref_Date < Date | is.na(Ref_Date)) %>% group_by(Person, Duration, Date, Type) %>% summarize(`Total Dur` = ifelse(first(Type) == "M", sum(Ref_Duration, na.rm = TRUE), NA), .groups = "drop") %>% # 补充备注(可选) mutate(`Total Dur` = case_when( Type == "M" & Person == "B" ~ paste0(`Total Dur`, "(第2、3行Duration之和)"), Type == "M" & Person == "C" ~ paste0(`Total Dur`, "(仅第4行,第1行不在前一周)"), TRUE ~ NA_character_ ))
最终得到的结果和预期一致:
| Person | Duration | Date | Type | Total Dur |
|---|---|---|---|---|
| C | 10 | 2022-01-29 | T | |
| B | 14 | 2022-02-01 | T | |
| B | 12 | 2022-02-01 | T | |
| C | 34 | 2022-02-01 | T | |
| B | 45 | 2022-02-08 | M | 26(第2、3行Duration之和) |
| C | 11 | 2022-02-08 | M | 34(仅第4行,第1行不在前一周) |
内容的提问来源于stack exchange,提问作者macfaro
相关产品推荐
相关产品推荐

