如何在 R 中添加两个结构为时间戳的字符变量和 return 字符输出?

How do I add two character variables that are structured as timestamps in R and return a character output?

我试图在 R 中将两个“时间戳”加在一起。我在引号中说时间戳是因为它们是字符变量,在技术上不是时间。 ExtractionTime列的数据是视频的minute/second点,PropertyTime列的数据是视频需要剪切的点的时间戳。理想情况下,我想在 ClipTime 列中添加 ExtractionTimePropertyTime,然后 return 它们的总和。我已经创建了执行此操作的代码,但一旦代码达到 59 秒,它就不会增加分钟数。知道如何做到这一点吗?谢谢!

这是我的一些数据:

ExtractionTime
<chr>
PropertyTime
<chr>
ClipTime
<lgl>
00:16:49    10:00:13    NA      
00:16:50    10:00:13    NA      
00:16:51    10:00:13    NA      
00:16:52    10:00:13    NA      
00:16:53    10:00:13    NA      
00:16:54    10:00:13    NA  

这是我的代码:

time.combine=function(x, y)
  for (i in seq_len(length(x))) {
    first.ex<-as.numeric(sub("(\d+):(\d+):(\d+)", "\1", x))
    second.ex<-as.numeric(sub("(\d+):(\d+):(\d+)", "\2", x))
    third.ex<-as.numeric(sub("(\d+):(\d+):(\d+)", "\3", x))
    first.prop<-as.numeric(sub("(\d+):(\d+):(\d+)", "\1", y))
    second.prop<-as.numeric(sub("(\d+):(\d+):(\d+)", "\2", y))
    third.prop<-as.numeric(sub("(\d+):(\d+):(\d+)", "\3", y))
    
    first<-first.ex+first.prop
    second<-second.ex+second.prop
    third<-third.ex+third.prop

 combined.times<-paste(first,second,third, sep = ":")
    return(combined.times)
  }

test.df$ClipTime<-time.combine(test.df$ExtractionTime, test.df$PropertyTime)

这导致...


ExtractionTime
<chr>
PropertyTime
<chr>
ClipTime
<chr>
00:16:49    10:00:13    10:16:62        
00:16:50    10:00:13    10:16:63        
00:16:51    10:00:13    10:16:64        
00:16:52    10:00:13    10:16:65        
00:16:53    10:00:13    10:16:66        
00:16:54    10:00:13    10:16:67

但我想要的是...

ExtractionTime
<chr>
PropertyTime
<chr>
ClipTime
<chr>
00:16:49    10:00:13    10:17:02        
00:16:50    10:00:13    10:17:03        
00:16:51    10:00:13    10:17:04        
00:16:52    10:00:13    10:17:05        
00:16:53    10:00:13    10:17:06        
00:16:54    10:00:13    10:17:07

我怎样才能得到这些数据?

您可以使用 lubridate 来自动执行其中的一些操作,但我有两个函数可用于快速转换为 HH:MM:SS 和从 HH:MM:SS 转换:

time2num <- function(x) {
  vapply(strsplit(x, ':'), function(y) sum(as.numeric(y) * c(60*60, 60, 1)),
         numeric(1), USE.NAMES=FALSE)
}
num2time <- function(x, digits.secs = getOption("digits.secs", 3)) {
  hr <- as.integer(x %/% 3600)
  min <- as.integer((x - 3600*hr) %/% 60)
  sec <- (x - 3600*hr - 60*min)
  if (anyNA(digits.secs)) {
    # a mostly-arbitrary determination of significant digits,
    # motivated by @Roland 
    for (digits.secs in 1:6) {
      if (any(abs(signif(sec, digits.secs) - sec) > (10^(-3 - digits.secs)))) next
      digits.secs <- digits.secs - 1L
      break
    }
  }
  sec <- sprintf(paste0("%02.", digits.secs[[1]], "f"), sec)
  sec <- paste0(ifelse(grepl("^[0-9]\.", sec), "0", ""), sec)
  out <- sprintf("%02i:%02i:%s", hr, min, sec)
  out[is.na(x)] <- NA_character_
  out
}

这样,

num2time(sum(time2num(c("00:16:49", "10:00:13"))), 0)
# [1] "10:17:02"

time2num 将冒号分隔的类似时间的字符串转换为数字(它只是将最小到最大的有效数字乘以 1、60 和 3600),

time2num(c("00:16:49", "10:00:13"))
# [1]  1009 36013

然后可以作为numeric进行操作,然后转换回“HH:MM:SS”格式。

像这样简单地写下来:

library(tidyverse)
library(lubridate)

df = tribble(
  ~ExtractionTime, ~PropertyTime,
  "00:16:49", "10:00:13", 
  "00:16:50", "10:00:13", 
  "00:16:51", "10:00:13", 
  "00:16:52", "10:00:13", 
  "00:16:53", "10:00:13", 
  "00:16:54", "10:00:13", 
)

df %>% mutate(
  ExtractionTime = ExtractionTime %>% hms() %>% as.duration(),
  PropertyTime = PropertyTime %>% hms() %>% as.duration(),
  ClipTime = (ExtractionTime + PropertyTime) %>% as.period())
)

输出

# # A tibble: 6 x 3
# ExtractionTime         PropertyTime       ClipTime  
# <Duration>             <Duration>         <Period>  
# 1 1009s (~16.82 minutes) 36013s (~10 hours) 10H 17M 2S
# 2 1010s (~16.83 minutes) 36013s (~10 hours) 10H 17M 3S
# 3 1011s (~16.85 minutes) 36013s (~10 hours) 10H 17M 4S
# 4 1012s (~16.87 minutes) 36013s (~10 hours) 10H 17M 5S
# 5 1013s (~16.88 minutes) 36013s (~10 hours) 10H 17M 6S
# 6 1014s (~16.9 minutes)  36013s (~10 hours) 10H 17M 7S

更新 1 好的。我不知道输出必须是 chr。所以让我们换个方式吧。

AddTime = function(t1, t2) {
  (t1 %>% hms() %>% as.duration()) + 
    (t2 %>% hms() %>% as.duration())
}

DurationToStr = function(t) {
  td = t %>% seconds_to_period
  sprintf('%02d:%02d:%02d', td@hour, minute(td), second(td))
}

df %>% mutate(
  ClipTime = AddTime(ExtractionTime, PropertyTime) %>% DurationToStr())

输出

# A tibble: 6 x 3
  ExtractionTime PropertyTime ClipTime
  <chr>          <chr>        <chr>   
1 00:16:49       10:00:13     10:17:02
2 00:16:50       10:00:13     10:17:03
3 00:16:51       10:00:13     10:17:04
4 00:16:52       10:00:13     10:17:05
5 00:16:53       10:00:13     10:17:06
6 00:16:54       10:00:13     10:17:07