2011-11-20 5 views
5

Szukam całej pomocy dla funkcji R, która może przekonwertować przedział czasowy, na przykład "15 min" lub "1 godzina" lub "6 s" lub "1 dzień" w obiekcie datetime, takim jak "00:15:00" lub "01:00:00" lub "00:00:06" lub "1960- 01-02 00:00:00 "(nie jestem tego pewien). Jestem pewien, że taka funkcja istnieje, lub istnieje schludny sposób, aby uniknąć programowania ...Od przedziału czasowego (na przykład "15 min" lub "2 s") do "00:15:00" lub "00:00:02"

Aby być bardziej szczegółowym chciałbym zrobić coś takiego (używając wymyślonej nazwy funkcji transform.span.to.time)

library(chron) 

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

który powinien dawać ten sam efekt jak

times("00:15:00") 

działa funkcję jak transform.span.to.time ("15 minut"), która zwraca na przykład „00:15:00 "istnieje czy istnieje sztuczka, jak to zrobić?

Odpowiedz

3

Funkcja baza ?cut.POSIXt to działa przez określony zestaw wartości dla 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.* 

Zobacz kod źródłowy wpisując cut.POSIXt, odpowiedni odcinek rozpoczyna się następująco:

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

Możesz przyjąć kod w tej sekcji, aby działał zgodnie z Twoimi potrzebami.

6

Przyjmujemy pojedynczą spację oddzielającą liczby i jednostki, a także brak spacji po jednostce "secs". Będzie to dotyczyło jednostek mieszanych:

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 
2

@DWin: dziękuję.

oparciu o przykład Dwin I łączyć się trochę i oto wynik:

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)) 
3

Można zdefiniować przedział czasowy z 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") 
} 

Na przykład:

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

EDYCJA: zmodyfikowano, aby uzyskać ciąg znaków akceptowalny dla chron times.

4

Pierwsze rozwiązanie wykorzystuje strapply w pakiecie gsubfn i przekształca się w dni, na przykład 1 godzina to 1/24 dnia. Drugie rozwiązanie przekształca się w wyrażenie R, które oblicza liczbę dni, a następnie ocenia je.

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) 

tutaj to drugie rozwiązanie:

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)) 
} 

testy:

> 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 
Powiązane problemy