如何用dplyr按学生和日期计算有效连接时长总和?
解决dplyr计算学生每日Initial-Final时长差之和的问题
我来帮你修正这个问题——你的核心问题是没有区分Connection的类型,导致diff()计算了所有相邻时间的差值,包括Final到下一个Initial的无效间隔,这才出现了A在2014-04-17得到625分钟的错误结果。
下面是正确的实现步骤和代码:
步骤说明
- 合并日期与时间:先把
Dates和Time字段合并成完整的POSIXct时间对象,这样计算时间差更准确直观。 - 分组排序:按
Student和Dates分组后,确保每组内的时间是按顺序排列的(虽然你的原始数据已经有序,但这一步能让代码更健壮)。 - 配对Initial与Final:用
lead()函数为每个Initial行匹配对应的Final时间(也就是下一行的时间,因为数据中每对都是Initial紧跟Final)。 - 计算有效时长差:只保留Initial行,计算每对Initial-Final的时间差并求和,最后转换为分钟并保留两位小数。
完整代码
library(dplyr) # 定义初始数据框 Paper <- data.frame( Student = c("A", "A", "A", "A", "A", "A", "B", "B", "B", "B"), Dates = c("2014-04-17", "2014-04-17", "2014-04-17", "2014-04-17", "2014-04-18", "2014-04-18", "2014-04-18", "2014-04-18", "2014-04-18","2014-04-18"), Time = c("10:35:00", "11:25:00", "19:15:00", "21:00:00", "22:00:00", "22:21:26", "10:25:00", "11:15:00", "16:05:00", "17:25:00"), Connection = c("Initial", "Final", "Initial", "Final", "Initial", "Final", "Initial", "Final", "Initial", "Final") ) # 合并日期和时间为完整的POSIXct时间对象 Paper <- Paper %>% mutate(datetime = as.POSIXct(paste(Dates, Time), format = "%Y-%m-%d %H:%M:%S")) # 计算每组内的有效时长差之和 FinalPaper <- Paper %>% group_by(Student, Dates) %>% # 确保每组内按时间排序 arrange(datetime, .by_group = TRUE) %>% # 为每个Initial匹配对应的Final时间 mutate(final_datetime = lead(datetime)) %>% # 仅保留Initial行,计算每对的时长差(单位:分钟)并求和 filter(Connection == "Initial") %>% summarise(`Time (Minutes)` = sum(difftime(final_datetime, datetime, units = "mins"))) %>% # 保留两位小数 mutate(`Time (Minutes)` = round(`Time (Minutes)`, digits = 2)) %>% # 将日期格式化为需求的dd-mm-yy样式 mutate(Dates = format(as.Date(Dates), "%d-%m-%y")) # 查看结果 FinalPaper
输出结果
运行后你会得到和预期完全一致的结果:
# A tibble: 3 × 3 # Groups: Student [2] Student Dates `Time (Minutes)` <chr> <chr> <dbl> 1 A 17-04-14 155 2 A 18-04-14 21.4 3 B 18-04-14 130
这个方案通过明确筛选Initial行并匹配对应Final时间,避免了无效的时间间隔被计入总和,完美解决了你的问题。
内容的提问来源于stack exchange,提问作者Luis Mompô
相关产品推荐
相关产品推荐

