Как мне преобразовать произвольную продолжительность (формат времени (HMS)) в минуты в R? - PullRequest
0 голосов
/ 04 мая 2018

У меня есть символьный вектор вида

duration <- c("57M8S","31S","2H20M31S", "21M32S")

Я хочу преобразовать весь вектор в минуты, чтобы получить результат, подобный

c(57.13, 0.52, 140.52, 21.53)

Как мне это сделать?
Я попытался использовать strsplit(duration,[A-Z]), это дает мне список векторов символов.
Но это имеет неравномерное количество элементов.
Может кто-нибудь, пожалуйста, направьте меня.

1 Ответ

0 голосов
/ 04 мая 2018

Вы можете сделать что-то вроде этого

duration <- c("57M8S","31S","2H20M31S", "21M32S")

sapply(duration, function(x) {
    v <- as.numeric(unlist(strsplit(x, "[HMS]")));
    return(sum(60^(rev(seq_along(v) - 2)) * v));
})
#     57M8S         31S    2H20M31S      21M32S
#57.1333333   0.5166667 140.5166667  21.5333333

Объяснение: Разделить записи на любой символ HMS; затем умножьте каждое значение на 60^k, где показатель степени k определяется числом делений минус 2. Таким образом, если мы получим только одно значение после разделения, оно будет обозначать секунды, и мы умножим эту запись на 60^(-1), чтобы преобразовать в минуты.


Или продемонстрировать более явно (и более неловко):

sapply(duration, function(x) {
    v <- as.numeric(unlist(strsplit(x, "[HMS]")));
    if (length(v) == 1) val <- v / 60;
    if (length(v) == 2) val <- v[1] + v[2] / 60;
    if (length(v) == 3) val <- v[1] * 60 + v[2] + v[3] / 60;
    return(val);
})

Другой интересный подход @akrun использует пакет gsubfn для замены H на * 60 +, M на * 1 + и S на * 1/60 +, перед eval с использованием полученной строки:

library(gsubfn);
sapply(sub(
    " \\+$", "", 
        gsubfn("([HMS])", list(H = "* 60 +",M = "* 1 +", S = "* 1/60 +"), duration)), 
    function(x) eval(parse(text= x)))
#    57* 1 +8* 1/60               31* 1/60 2* 60 +20* 1 +31* 1/60
#        57.1333333              0.5166667            140.5166667
#   21* 1 +32* 1/60
#        21.5333333
...