R 计算午夜后的小时数

R calculate hours after midnight

提问人:Minh Chau 提问时间:11/11/2023 最后编辑:benson23Minh Chau 更新时间:11/11/2023 访问量:56

问:

我想使用 R 来计算 R 中两个军事时间(例如,13:00 和 7:00)之间的时差。

编号 开始时间 结束时间
1 18:00 2:00
2 18:00 20:00
3 2:00 4:00

我想计算 start.time 和 end.time 之间的时间差。我希望我的结果如下:

编号 开始时间 结束时间 差异
1 18:00 2:00 8
2 18:00 20:00 2
3 2:00 4:00 2

如。POSIXct() 和 difftime() 我尝试使用并将 start.time 和 end.time 转换为 datetime 类,并用于查找它们之间的时间差。这仅适用于 2 和 3。对于第一个,参数将所有时间都变成同一个日期,因此它们之间的差值不等于 8。as.posixct(start.time, format = '%H:%M')as.POSIXct(end.time, format = '%H:%M')difftime()as.POSIXct()

我的问题是:有没有可以考虑所有这些场景的代码?

R 时间 润滑剂

评论


答:

0赞 Nicholas Ray 11/11/2023 #1

以下代码将实现您正在寻找的内容,尽管它可能难以概括。

data<-data.frame(
  id=c(1,2,3),
  start.time=c("18:00","18:00","2:00"),
  end.time=c("2:00","20:00","4:00")
)
library(tidyverse)
data<-mutate(data,
             start.time=as.numeric(gsub("\\:.*","",start.time)),
             end.time=as.numeric(gsub("\\:.*","",end.time)),
             diff=ifelse(end.time>start.time,end.time-start.time,
                         (24-start.time)+end.time))

你只需从 if 中减去 if 更大。如果较大,则先从 24 中减去,然后添加 。这取决于分钟数无关紧要,因为我过去常常删除 .end.timestart.timeend.timestart.timestart.timeend.timegsub():

0赞 benson23 11/11/2023 #2

您可以先将小时数转换为 R POSIXct 对象,然后添加一天(如果它早于 )。最后用于计算它们的小时差并删除任何不需要的列(最终函数)。end.timestart.timedifftimeselect

library(dplyr)

df %>% mutate(across(ends_with("time"), ~as.POSIXct(.x, format = '%H:%M'), .names = "{.col}2"),
              end.time2 = if_else(end.time2 < start.time2, end.time2 + 1*60*60*24, end.time2),
              difftime = difftime(end.time2, start.time2)) %>% 
  select(-ends_with("2"))

  id start.time end.time difftime
1  1      18:00     2:00  8 hours
2  2      18:00    20:00  2 hours
3  3       2:00     4:00  2 hours

评论

1赞 Minh Chau 11/11/2023
嗨,本森,谢谢你的回答。你的方式最适合我当前的项目。
0赞 jay.sf 11/11/2023 #3

您可以将 24*60^2 秒(一天)添加到行差异小于零的日期时间。由于结果是秒,我们将其除以 。 这里会快如闪电。60^2matrixStats::rowDiffs

> transform(dat, 
+           diff=sapply(dat[2:3], as.POSIXct, format='%H:%M') |>
+             {\(.) {
+               nw_dy <- matrixStats::rowDiffs(.) < 0
+               .[nw_dy, 2] <- .[nw_dy, 2] + 24*60^2
+               unname(.)
+             }}() |>
+             matrixStats::rowDiffs()/60^2)
  id start.time end.time diff
1  1      18:00     2:00    8
2  2      18:00    20:00    2
3  3       2:00     4:00    2

如果没有 matrixStats,您可以执行以下操作,当然,这会更慢:

> transform(dat, 
+           diff=sapply(dat[2:3], as.POSIXct, format='%H:%M') |>
+             {\(.) {
+               nw_dy <- .[, 'end.time'] - .[, 'start.time'] < 0
+               .[nw_dy, 2] <- .[nw_dy, 2] + 24*60^2
+               unname(.)
+             }}() |>
+             apply(1, diff)/60^2)
  id start.time end.time diff
1  1      18:00     2:00    8
2  2      18:00    20:00    2
3  3       2:00     4:00    2

数据:

> dput(dat)
structure(list(id = 1:3, start.time = c("18:00", "18:00", "2:00"
), end.time = c("2:00", "20:00", "4:00")), class = "data.frame", row.names = c(NA, 
-3L))