R语言 为什么在分组的时间框架上的ifelse()中计算时,我的时间差的单位不一致?

xt0899hw  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(142)

我正在计算两列之间的条件时间差,有人能解释一下为什么第一行以秒为单位返回,而第三行以分钟为单位返回? 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(),或者如果我使用difftime()并指定unit="mins"而不是一个简单的减法,这个问题就不会再出现了,但是我在这里试图理解为什么在当前代码中会发生这种情况。如果删除第二行的结尾和开头相同,这个问题也会消失。

编辑:

正如下面的两个答案所指出的,使用此代码,单位是特定于组的,它将被设置为适应组内存在的最小值。
下面更新的source Dataframe 也有间隔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)
)



每组单位:

  • 组1:秒(由第二行设置)
  • 第2组:分钟
  • 第3组:小时(第五行设置)
  • 第4组:天数
6mw9ycah

6mw9ycah1#

当减去时间时,difftime被调度,它试图“漂亮”而不是有一个默认的单位。如果直接使用difftime,你可以设置单位。这并不完全特定于你的代码,但显然difftime被单独应用于每个组,所以group_by是罪魁祸首,每个组都有自己的单位。

> reprex <- source %>%
+   group_by(group) %>%
+   mutate(length = ifelse(boolean_flag, difftime(end, start, units='secs'), 0)) %>%
+   ungroup()
> reprex
# A tibble: 3 × 5
  group start               end                 boolean_flag length
  <dbl> <dttm>              <dttm>              <lgl>         <dbl>
1     1 2023-12-01 00:00:00 2023-12-01 00:01:00 TRUE             60
2     1 2023-12-01 00:01:00 2023-12-01 00:01:00 TRUE              0
3     2 2023-12-01 00:00:00 2023-12-01 00:01:00 TRUE             60

字符串
我可以假设,你的真实的代码更复杂,或者为什么你需要分组来计算 * 每 * 行的时间差?

ctehm74n

ctehm74n2#

基本上,每个组的格式都会改变。当它“看到”零值时,它会动态调整输出格式。
解决方法是从lubridate使用as.duration

library(dplyr)
library(lubridate)

source %>% 
  group_by(group) %>% 
  mutate(length = ifelse(boolean_flag, as.duration(end - start), 0)) %>%
  ungroup()
# A tibble: 3 × 5
  group start               end                 boolean_flag length
  <dbl> <dttm>              <dttm>              <lgl>         <dbl>
1     1 2023-12-01 00:00:00 2023-12-01 00:01:00 TRUE             60
2     1 2023-12-01 00:01:00 2023-12-01 00:01:00 TRUE              0
3     2 2023-12-01 00:00:00 2023-12-01 00:01:00 TRUE             60

字符串

相关问题