От интервала времени (например, «15 минут» или «2 секунд») до «00:15:00» или «00:00:02» - PullRequest
5 голосов
/ 21 ноября 2011

Я ищу во всей справке функцию R, которая преобразует временной интервал, например, «15 минут», «1 час», «6 секунд» или «1 день», в объект даты и времени, например «00:15:00» или «01:00:00» или «00:00:06» или «1960-01-02 00:00:00» (не уверен в этом). Я уверен, что такая функция существует, или есть отличный способ избежать ее программирования ...

Чтобы быть более конкретным, я хотел бы сделать что-то вроде этого (используя составную функцию name transform.span.to.time):

library(chron)

times(transform.span.to.time("15 min"))

, который должен дать тот же результат, что и

times("00:15:00")

Существует ли такая функция, как transform.span.to.time ("15 мин"), которая возвращает что-то вроде "00:15:00", или существует хитрость, как это сделать?

Ответы [ 5 ]

6 голосов
/ 21 ноября 2011

Мы примем один пробел, разделяющий числа и единицы, а также не ставим пробел после единицы «сек»Это будет обрабатывать смешанные единицы:

test <- "0 hours 15 min 0 secs"

 transform.span <- function(test){ 
     testh <-         if(!grepl( " hour | hours ", "0 hours 15 min 0 secs")){ 
             # First consequent if no hours
                                      sub("^", "0:", test)} else { 
                                      sub(" hour | hours ", ":", test)}
     testm <- if(!grepl( " min | minutes ", testh)) {    
             #  first consequent if no minutes
                                      sub(" min | minutes ", "0:", testh)} else{
                                      sub(" min | minutes ", ":", testh)  }

     test.s <- if(!grepl( " sec| secs| seconds", testm)) { 
              # first consequent if no seconds
                                       sub(" sec| secs| seconds", "0", testm)} else{ 
                                       sub(" sec| secs| seconds", "", testm)}

     return(times(test.s)) }
###  Use
> transform.span(test)
[1] 00:15:00
> test2 <- "21 hours 15 min 38 secs"
> transform.span(test2)
[1] 21:15:38
4 голосов
/ 21 ноября 2011

Первое решение использует strapply в пакете gsubfn и преобразуется в дни, например, 1 час - это 1/24 дня.Второе решение преобразуется в выражение R, которое вычисляет количество дней и затем оценивает его.

library(gsubfn)
library(chron)

unit2days <- function(d, u) 
     as.numeric(d) * switch(tolower(u), s = 1, m = 60, h = 3600)/(24 * 3600)
transform.span.to.time <- function(x) 
     sapply(strapply(x, "(\\d+) *(\\w)", unit2days), sum)

Вот второе решение:

library(chron)

transform.span.to.time2 <- function(x) {
    x <- paste(x, 0)
    x <- sub("h\\w*", "*3600+", x, ignore.case = TRUE)
    x <- sub("m\\w*", "*60+", x, ignore.case = TRUE)
    x <- sub("s\\w*", "+", x, ignore.case = TRUE)
    unname(sapply(x, function(x) eval(parse(text = x)))/(24*3600))
}

Тесты:

> x <- c("12 hours 3 min 1 sec", "22h", "18 MINUTES 23 SECONDS")
>
> times(transform.span.to.time(x))
[1] 12:03:01 22:00:00 00:18:23
>
> times(transform.span.to.time2(x))
[1] 12:03:01 22:00:00 00:18:23
3 голосов
/ 21 ноября 2011

Вы можете определить промежуток времени с помощью difftime:

span2time <- function(span,  units = c('mins', 'secs', 'hours')) {
  span.dt <- as.difftime(span,  units = match.arg(units))
  format(as.POSIXct("1970-01-01") + span.dt, "%H:%M:%S")
}

Например:

> span2time(15)
[1] "00:15:00"

РЕДАКТИРОВАТЬ: изменено для получения строки символов, приемлемой для times. Chron.

3 голосов
/ 21 ноября 2011

Базовая функция ?cut.POSIXt выполняет эту работу для указанного набора значений для breaks:

breaks: a vector of cut points _or_ number giving the number of
      intervals which ‘x’ is to be cut into *_or_ an interval
      specification, one of ‘"sec"’, ‘"min"’, ‘"hour"’, ‘"day"’,
      ‘"DSTday"’, ‘"week"’, ‘"month"’, ‘"quarter"’ or ‘"year"’,
      optionally preceded by an integer and a space, or followed by
      ‘"s"’.  For ‘"Date"’ objects only ‘"day"’, ‘"week"’,
      ‘"month"’, ‘"quarter"’ and ‘"year"’ are allowed.*

Посмотрите исходный код, набрав cut.POSIXt, соответствующий раздел начинается с этого:

else if (is.character(breaks) && length(breaks) == 1L) {

Вы можете принять код в этом разделе, чтобы работать для ваших нужд.

2 голосов
/ 21 ноября 2011

@ DWin: спасибо.

На основе примера DWin я немного переставил, и вот результат:

transform.span<-function(timeSpan) { 
    timeSpanH <- if(!grepl(" hour | hours | hour| hours|hour |hours |hour|hours", timeSpan)) { 
                # First consequent if no hours
                sub("^", "00:", timeSpan)
            } else { 
                sub(" hour | hours | hour| hours|hour |hours |hour|hours", ":", timeSpan)
            }
    timeSpanM <- if(!grepl( " min | minutes | min| minutes|min |minutes |min|minutes", timeSpanH)) {    
                #  first consequent if no minutes
                paste("00:", timeSpanH, sep="")
            } else{
                sub(" min | minutes | min| minutes|min |minutes |min|minutes", ":", timeSpanH)  
            }
    timeSpanS <- if(!grepl( " sec| secs| seconds|sec|secs|seconds", timeSpanM)) { 
                # first consequent if no seconds
                paste(timeSpanM, "00", sep="")
            } else{ 
                sub(" sec| secs| seconds|sec|secs|seconds", "", timeSpanM)
            }

    return(timeSpanS) 
}
###  Use
test <- "1 hour 2 min 1 sec"
times(transform.span(test))
test1hour <- "1 hour"
times(transform.span(test1hour))
test15min <- "15 min"
times(transform.span(test15min))
test4sec <- "4 sec"
times(transform.span(test4sec))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...