分组DataFrame中ifelse计算时间差单位不一致的原因探究
为什么分组计算条件时间差时,不同行的时间单位不一致?
我在计算两列间的条件时间差时发现一个问题:第一行结果以秒为单位,第三行却以分钟为单位。我的DataFrame是按group字段分组处理的,代码如下:
library(dplyr) source <- data.frame( group = c(1,1,2), start = as.POSIXct(c("2023-12-01 00:00:00", "2023-12-01 00:01:00", "2023-12-01 00:00:00")), end = as.POSIXct(c("2023-12-01 00:01:00", "2023-12-01 00:01:00", "2023-12-01 00:01:00")), boolean_flag = c(TRUE, TRUE, TRUE) ) reprex <- source %>% group_by(group) %>% mutate(length = ifelse(boolean_flag, end - start, 0)) %>% ungroup() reprex
我知道改用if_else(),或者用指定unit="mins"的difftime()替代直接相减可以解决问题,但想搞明白当前代码出现这个问题的原因。另外,移除end与start相同的第二行后,问题也会消失。
问题原因
- 分组内计算
end - start得到的是difftime类型对象,R会自动为每个分组选择最合适的时间单位——这个单位由分组内的最小时间差决定。 - 在第一个数据集里:
- Group 1包含两行,第二行的时间差是0秒(组内最小),因此整个Group 1的时间单位被设为秒,第一行的60秒就显示为
60 secs。 - Group 2只有一行,时间差是1分钟,单位就设为分钟,显示为
1 mins。
- Group 1包含两行,第二行的时间差是0秒(组内最小),因此整个Group 1的时间单位被设为秒,第一行的60秒就显示为
- 而基础R的
ifelse()函数会破坏difftime的类型属性,合并不同分组的结果时,保留了各自的单位信息,最终导致同一列出现单位不一致的情况。用dplyr的if_else()(类型安全版本)则会统一输出类型,避免这个问题。
补充验证
更新后的数据集包含1天、1小时等不同跨度的时间差,能更清晰体现这个规律:
source <- data.frame( group = c(1,1,2,3,3,4), start = as.POSIXct(c("2023-12-01 00:00:00", "2023-12-01 00:01:00", "2023-12-01 00:00:00", "2023-12-01 00:00:00", "2023-12-01 00:00:00", "2023-12-01 00:00:00")), end = as.POSIXct(c("2023-12-01 00:01:00", "2023-12-01 00:01:00", "2023-12-01 00:01:00", "2023-12-02 00:00:00", "2023-12-01 01:00:00", "2023-12-01 01:00:00")), boolean_flag = c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE) )
各组对应的时间单位:
- Group 1:秒(由第二行的0秒时间差决定)
- Group 2:分钟
- Group 3:小时(由第五行的1小时时间差决定)
- Group 4:天
内容的提问来源于stack exchange,提问作者Vincent
相关产品推荐
相关产品推荐

