如何在 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
列中添加 ExtractionTime
和 PropertyTime
,然后 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
我试图在 R 中将两个“时间戳”加在一起。我在引号中说时间戳是因为它们是字符变量,在技术上不是时间。 ExtractionTime
列的数据是视频的minute/second点,PropertyTime
列的数据是视频需要剪切的点的时间戳。理想情况下,我想在 ClipTime
列中添加 ExtractionTime
和 PropertyTime
,然后 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