Tengo un vector de POSIXct valores y me gustaría alrededor de ellos a la más cercana al cuarto de hora. No me importa el día. ¿Cómo puedo convertir los valores en horas y minutos?

Por ejemplo, me gustaría que el valor

"2012-05-30 20:41:21 UTC"

a ser

"20:45"
InformationsquelleAutor Dominic | 2012-06-02

7 Comentarios

  1. 20

    De hecho, una vieja pregunta con algunas respuestas útiles hasta el momento. La última por giraffhere parece ser la más elegante. sin embargo, ist no floor_date pero round_date que va a hacer el truco:

    lubridate::round_date(x, "15 minutes") 
    • Buen punto de salida, va a agregar.
  2. 21

    Puede utilizar round. El truco es dividir por 900 segundos (15 minutos * 60 segundos) antes de redondeo y multiplicar por 900 después:

    a <-as.POSIXlt("2012-05-30 20:41:21 UTC")
    b <-as.POSIXlt(round(as.double(a)/(15*60))*(15*60),origin=(as.POSIXlt('1970-01-01')))
    b
    [1] "2012-05-30 20:45:00 EDT"

    Para obtener sólo la hora y los minutos, sólo tiene que utilizar el formato de

    format(b,"%H:%M")
    [1] "20:45"
    
    as.character(format(b,"%H:%M"))
    [1] "20:45"
    • No creo que tenemos un doble, y el origen acepta una cadena, tan ligeramente simplificada: b <-as.POSIXlt(round(as.numeric(a)/(15*60))*(15*60),origin='1970-01-01')
  3. 13

    Vieja pregunta, pero quisiera señalar que la lubridate paquete se encarga de esto fácilmente ahora con floor_date. Para cortar un vector de POSIXct objetos a intervalos de 15 minutos, que se usa como este.

    x <- lubridate::floor_date(x, "15 minutes")

    EDICIÓN: Destaca por el usuario @user3297928, uso lubridate::round_date(x, "15 minutes") para el redondeo al más cercano de 15 minutos. Los pisos por encima de ella.

  4. 4

    Puede utilizar el align.time función en el xts paquete para controlar el redondeo, entonces format para devolver una cadena de «HH:MM»:

    R> library(xts)
    R> p <- as.POSIXct("2012-05-30 20:41:21", tz="UTC")
    R> a <- align.time(p, n=60*15)  # n is in seconds
    R> format(a, "%H:%M")
    [1] "20:45"
    • +1 sombrero de punta a usted
    • Esta es elegante, pero parece que sólo ronda.
    • está 100% correcto. align.time sólo rondas y que quería redondear a la más cercana al cuarto de hora. Disculpas.
    • para redondear hacia abajo: align.time(p - lubridate::minutes(15), n=60*15)
  5. 3

    Probar este, que combina tanto las solicitudes y se basa en mirar qué round.POSIXt() y trunc.POSIXt() hacer.

    myRound <- function (x, convert = TRUE)  {
        x <- as.POSIXlt(x)
        mins <- x$min
        mult <- mins %/% 15
        remain <- mins %% 15
        if(remain > 7L || (remain == 7L && x$sec > 29))
            mult <- mult + 1
        if(mult > 3) {
            x$min <- 0
            x <- x + 3600
        } else {
            x$min <- 15 * mult
        }
        x <- trunc.POSIXt(x, units = "mins")
        if(convert) {
            x <- format(x, format = "%H:%M")
        }
        x
    }

    Esto da:

    > tmp <- as.POSIXct("2012-05-30 20:41:21 UTC")
    > myRound(tmp)
    [1] "20:45"
    > myRound(tmp, convert = FALSE)
    [1] "2012-05-30 20:45:00 BST"
    > tmp2 <- as.POSIXct("2012-05-30 20:55:21 UTC")
    > myRound(tmp2)
    [1] "21:00"
    > myRound(tmp2, convert = FALSE)
    [1] "2012-05-30 21:00:00 BST"
    • esto parece no ser vectorizados bien, trate de structure(c(1313331280, 1313334917, 1313334917, 1313340309, 1313340309, 1313340895, 1313340895, 1313341133, 1313341218, 1313341475), class = c("POSIXct", "POSIXt"), tzone = "UTC")
  6. 3

    Utilizando IDate y ITime clases de data.table y un IPeriod clase (desarrollado) yo era capaz de obtener la solución más escalable.

    Sólo shhhhimhuntingrabbits y PLapointe responder a la pregunta en términos de más cercano. xts solución rondas de sólo el uso de techo, mi IPeriod solución permite especificar techo o piso.

    Para obtener el máximo rendimiento que usted necesita para mantener sus datos en IDate y ITime clases. Como se ve en el punto de referencia que es barato de producir POSIXct de IDate/ITime/IPeriod. Por debajo de referencia de algunos 22M timestamp:

    # install only if you don't have
    install.packages(c("microbenchmarkCore","data.table"),
    repos = c("https://olafmersmann.github.io/drat",
    "https://jangorecki.github.io/drat/iperiod"))
    library(microbenchmarkCore)
    library(data.table) # iunit branch
    library(xts)
    Sys.setenv(TZ="UTC")
    ## some source data: download and unzip csv
    # "http://api.bitcoincharts.com/v1/csv/btceUSD.csv.gz"
    # below benchmark on btceUSD.csv.gz 11-Oct-2015 11:35 133664801
    system.nanotime(dt <- fread(".btceUSD.csv"))
    # Read 21931266 rows and 3 (of 3) columns from 0.878 GB file in 00:00:10
    #     user   system  elapsed 
    #       NA       NA 9.048991
    # take the timestamp only
    x = as.POSIXct(dt[[1L]], tz="UTC", origin="1970-01-01")
    # functions
    shhhhi <- function(your.time){
    strptime("1970-01-01", "%Y-%m-%d", tz="UTC") + round(as.numeric(your.time)/900)*900
    }
    PLapointe <- function(a){
    as.POSIXlt(round(as.double(a)/(15*60))*(15*60),origin=(as.POSIXlt('1970-01-01')))
    }
    # myRound - not vectorized
    # compare results
    all.equal(
    format(shhhhi(x),"%H:%M"),
    format(PLapointe(x),"%H:%M")
    )
    # [1] TRUE
    all.equal(
    format(align.time(x, n = 60*15),"%H:%M"),
    format(periodize(x, "mins", 15),"%H:%M")
    )
    # [1] TRUE
    # IPeriod native input are IDate and ITime - will be tested too
    idt <- IDateTime(x)
    idate <- idt$idate
    itime <- idt$itime
    microbenchmark(times = 10L,
    shhhhi(x),
    PLapointe(x),
    xts = align.time(x, 15*60),
    posix_ip_posix = as.POSIXct(periodize(x, "mins", 15), tz="UTC"),
    posix_ip = periodize(x, "mins", 15),
    ip_posix = as.POSIXct(periodize(idate, itime, "mins", 15), tz="UTC"),
    ip = periodize(idate, itime, "mins", 15))
    # Unit: microseconds
    #            expr         min          lq         mean       median          uq         max neval
    #       shhhhi(x)  960819.810  984970.363 1127272.6812 1167512.2765 1201770.895 1243706.235    10
    #    PLapointe(x) 2322929.313 2440263.122 2617210.4264 2597772.9825 2792936.774 2981499.356    10
    #             xts  453409.222  525738.163  581139.6768  546300.9395  677077.650  767609.155    10
    #  posix_ip_posix 3314609.993 3499220.920 3641219.0876 3586822.9150 3654548.885 4457614.174    10
    #        posix_ip 3010316.462 3066736.299 3157777.2361 3133693.0655 3234307.549 3401388.800    10
    #        ip_posix     335.741     380.696     513.7420     543.3425     630.020     663.385    10
    #              ip      98.031     151.471     207.7404     231.8200     262.037     278.789    10

    IDate y ITime correctamente las escalas, no sólo en esta tarea en particular. Ambos tipos, lo mismo que IPeriod, se entero de base. Quiero suponer que también la escala de niza en unirse a la agrupación o por datetime campos.

    Manual en línea: https://jangorecki.github.io/drat/iperiod/

    • Gracias por el post, pero podéis explicar cómo en realidad instalar este paquete? No está claro en cualquier parte de la documentación.
    • Véase el primer comando en el bloque de código para instalar desde publicada repo. De lo contrario, la manera más fiable es conseguir que el iunit de la sucursal, usted puede agregar a remoto y la caja de la sucursal. Está basado en Octubre 2015 de datos.tabla.
    • Ah, me olvidaba de esa línea. Yo había asumido que tendría un paquete separado que se llama «periodize» o «IPeriod» o algo así, frente a una bifurcación de datos.tabla. Creo que es algo lamentable que el IDateTime cosas está incluido en los datos.tabla y no en un paquete separado
    • pero IPeriod clase es simplemente una numérico, cualquier paquete que se puede manejar sólo con %/% operador, teniendo períodos codificado incluso hay ninguna necesidad para almacenar los atributos, sólo un número, no la magia negra.
    • La abstracción es valioso de la omi
    • de acuerdo, pero extraer sólo que a un paquete separado que no es tan necesario como datos.la tabla es una ligera dependencia ya está. Se puede importar sólo para IDateTime sin problemas. Tenga en cuenta que hay planificada una de las extensiones de IDateTime clases de datos.la tabla de datos.tabla#1451, sería bueno IPeriod manejar nanosegundos demasiado.

Dejar respuesta

Please enter your comment!
Please enter your name here