Мы могли бы split
на границе между буквой и цифрой, затем преобразовать ее в data.frame
и использовать rbindlist
из data.table
library(data.table)
rbindlist(
lapply(strsplit(s1, "(?<=[A-Z])(?=[0-9])|(?<=[0-9])(?=[A-Z])", perl = TRUE),
function(x) {
x1 <- x[-1];val <- x1[seq(1, length(x1), by = 2)]
nm <- x1[seq(2, length(x1), by = 2)]
setNames(as.data.frame.list(val), nm)}),
fill = TRUE)
# H M S
#1: 1 57 3
#2: 1 3 46
#3: 1 NA 33
#4: 1 2 NA
#5: NA NA 18
#6: NA 18 9
#7: 1 39 22
Мы могли бы также сделать это с tidyverse
library(tidyverse)
library(stringi)
out <- map2_df(stri_extract_all_regex(s1, "\\d+"),
stri_extract_all_regex(s1, "[HMS]"), ~ .x %>%
as.integer %>%
as.list %>%
set_names(.y) )
out
#A tibble: 7 x 3
# H M S
# <int> <int> <int>
#1 1 57 3
#2 1 3 46
#3 1 NA 33
#4 1 2 NA
#5 NA NA 18
#6 NA 18 9
#7 1 39 22
Если нам нужно заменить NA
на 0
out[is.na(out)] <- 0
Или, если нам нужно сделать это путем преобразования во временной класс,
library(lubridate)
v1 <- parse_date_time(sub("^PT", "", s1),
order = rlang::syms(tolower(unique(gsub("[^HMS]+", "", s1)))))
tibble(Hour = hour(v1), Minute = minute(v1), Seconds = seconds(v1))
# A tibble: 7 x 3
# Hour Minute Seconds
# <int> <int> <dbl>
#1 1 57 3
#2 1 3 46
#3 1 0 33
#4 1 0 2
#5 0 0 18
#6 18 0 9
#7 1 39 22
Здесь мы подобрали форматы программно из строки ввода
Или мы можем сделать только с base R
v1 <- do.call(pmax, c(lapply(paste0("PT", gsub("(.)", "%\\1\\1",
unique(gsub("[^HMS]+", "", s1)))), strptime, x = s1), list(na.rm= TRUE)))
data.frame(hour = v1$hour, minute = v1$min, sec = v1$sec)
# hour minute sec
#1 1 57 3
#2 1 3 46
#3 1 0 33
#4 1 2 0
#5 0 0 18
#6 0 18 9
#7 1 39 22