2013-05-29 9 views
9

Sto cercando di raggruppare le date in R con un livello arbitrario di precisione.arrotondare una data in R a un livello arbitrario di precisione

È piuttosto semplice eseguire l'operazione all'ora o al minuto più vicini, utilizzando ad es. lubridate:

library(lubridate) 
nearest_hour = floor_date(now(), 'hour') 

È quindi possibile raggruppare un elenco di tali date con per esempio un semplice summariseddply da plyr.

Quello che mi piacerebbe fare è arrotondare le date con precisione arbitraria, ad es. con l'approssimazione di 15 minuti o ogni 3 ore:

nearest_three_hours = floor_date(now(), '3 hours') 

C'è una discussione di queste cose a http://r.789695.n4.nabble.com/Truncating-dates-and-other-date-time-manipulations-td866901.html ma al di fuori di date taglio, non ci non sembra essere stato qualsiasi risoluzione.

Qualsiasi aiuto apprezzato! Grazie.

+2

Se si dispone di un vettore di volte per sottoinsieme da allora potresti usare la funzione 'endpoints' in [xts] (http://cran.project.org/package=xts):' library (xts); x <- .POSIXct (0) +1: 10 * 60 * 60 ; x [endpoint (x, "ore", 3)] ' – GSee

risposta

5

lubrifica già i piani all'unità atomica più vicina. Per ottenere il piano per i 15 minuti più vicini, che penso sia quello che vuoi fare (non intorno), devi solo mappare nell'intervallo corretto tramite findInterval e un insieme definito di punti di interruzione. Prova questo floor_time, che è funzionalmente equivalente a floor_date, ma ti consente di specificare un numero variabile di unità per secondi, minuti o ore.

floor_time <- function(x, k = 1, unit = c("second", "minute", "hour", "day", 
              "week", "month", "year")) { 
    require(lubridate) 

    nmax <- NULL 

    switch(unit, second = {nmax <- 60}, 
     minute = {nmax <- 60}, 
     hour = {nmax <- 24}) 

    cuts <- seq(from = 0, to = nmax - 1, by = k) 
    new <- switch(unit, 
       second = update(x, seconds = cuts[findInterval(second(x), cuts)]), 
       minute = update(x, minutes = cuts[findInterval(minute(x), cuts)], 
           seconds = 0), 
       hour = update(x, hours = cuts[findInterval(hour(x), cuts)], 
           minutes = 0, seconds = 0), 
       day = update(x, hours = 0, minutes = 0, seconds = 0), 
       week = update(x, wdays = 1, hours = 0, minutes = 0, seconds = 0), 
       month = update(x, mdays = 1, hours = 0, minutes = 0, seconds = 0), 
       year = update(x, ydays = 1, hours = 0, minutes = 0, seconds = 0)) 

    new 
} 
5

Si può provare questo, ancora basato sul lubridate biblioteca

library(lubridate) 
round_minute<-function(x,precision){ 
    m<-minute(x)+second(x)/60 
    m.r<- round(m/precision)*precision 
    minute(x)<-m.r 
    second(x)<-0 
    x 
} 

round_minute(ymd_hms(c("2013-06-03 22:53:00","2013-05-03 12:18:00","2013-05-03 00:10:00")),15) 

> "2013-06-03 23:00:00 UTC" "2013-05-03 12:15:00 UTC" "2013-05-03 00:15:00 UTC" 

Il codice di gestire bene tutte le situazioni più complesse grazie alla lubridate. Ovviamente questa funzione funziona solo per la precisione espressa in minuti, ma è possibile estenderla facilmente ad altre unità e persino creare una funzione generica se davvero ne hai bisogno.

1

lubridate ora ha una funzione più generica round_date().

lubridate::round_date(date, "5 mins") 
lubridate::round_date(date, "2 hours") 
1

Un po 'in ritardo, e non ho rappresentante di commentare, ma come detto Selva, lubridate ora ha questa funzionalità:

library(lubridate) 
round_date(now(), '3 hours') 
floor_date(now(), '3 hours') 
ceiling_date(now(), '3 hours') 
Problemi correlati