2012-01-06 10 views
6

¿Cuál es la mejor manera de obtener el período de tiempo representado por interval en lubridate, en unidades especificadas? Todo lo que puedo imaginar es algo así como lo siguiente desordenado:Longitud del intervalo lubridate

> ival 
[1] 2011-01-01 03:00:46 -- 2011-10-21 18:33:44 

> difftime(attr(ival, "start") + as.numeric(ival), attr(ival, "start"), 'days') 
Time difference of 293.6479 days 

(que también añade esto como una solicitud de función en https://github.com/hadley/lubridate/issues/105, bajo el supuesto de que no hay mejor manera disponible - pero tal vez alguien aquí sabe de uno.)

Actualización - Al parecer, la función difftime tampoco lo hace. Aquí hay un ejemplo.

> (d1 <- as.POSIXct("2011-03-12 12:00:00", 'America/Chicago')) 
[1] "2011-03-12 12:00:00 CST" 
> (d2 <- d1 + days(1)) # Gives desired result 
[1] "2011-03-13 12:00:00 CDT" 
> (i2 <- d2 - d1) 
[1] 2011-03-12 12:00:00 -- 2011-03-13 12:00:00 
> difftime(attr(i2, "start") + as.numeric(i2), attr(i2, "start"), 'days') 
Time difference of 23 hours 

Como menciono a continuación, creo que una buena manera de manejar esto sería para implementar una función /.interval que no lo hace primero en arrojar su entrada a un period.

+0

Usted dice que desea un intervalo en una unidad en particular, pero por el contexto de los comentarios a continuación, parece que desea redondearlo a la unidad completa más cercana. Si es así, ¿puedes editar más para que quede claro? –

+0

No, no quiero que sea redondeado. Tal vez las ediciones que acabo de hacer ayudan a aclarar? –

Respuesta

10

La función as.duration es lo que lubricante proporciona. La clase de intervalo se representa internamente como la cantidad de segundos desde el inicio, por lo que si desea el número de horas, simplemente puede dividir as.numeric(ival) entre 3600 o entre (3600 * 24) durante días.

Si desea ejemplos de funciones trabajadas aplicadas a su objeto, debe proporcionar el resultado de dput(ival). Hice mi prueba en los objetos creados en la página help(duration) que es donde me envió ?interval.

date <- as.POSIXct("2009-03-08 01:59:59") # DST boundary 
date2 <- as.POSIXct("2000-02-29 12:00:00") 
span <- date2 - date #creates interval 
span 
#[1] 2000-02-29 12:00:00 -- 2009-03-08 01:59:59 
str(span) 
#Classes 'interval', 'numeric' atomic [1:1] 2.85e+08 
# ..- attr(*, "start")= POSIXct[1:1], format: "2000-02-29 12:00:00" 
as.duration(span) 
#[1] 284651999s (9.02y) 
as.numeric(span)/(3600*24) 
#[1] 3294.583 
# A check against the messy method: 
difftime(attr(span, "start") + as.numeric(span), attr(span, "start"), 'days') 
# Time difference of 3294.583 days 
+0

Gracias, pero eso no es correcto: 3600 * 24 no siempre es la cantidad de segundos en un día. Lo que trato de hacer es aprovechar los sistemas que ya manejan cosas como DST, etc. –

+0

@ KenWilliams No entiendo por qué piensas que esto está mal. '? duration' parece implicar que de hecho respeta el horario de verano, al igual que' difftime'. Cuando convierto tu ejemplo usando 'as.duration' obtengo exactamente la misma respuesta que obtuviste usando' difftime'. – joran

+0

También puede dividir duraciones por días (1) – hadley

3

Ken, Dividir por días (1) le dará lo que quiere. Lubridate no coacciona períodos a duraciones cuando divide intervalos por períodos. (Aunque el algoritmo para encontrar el número exacto de períodos completos en el intervalo comienza con una estimación que usa el intervalo dividido por el número análogo de duraciones, que podría ser lo que está notando).

El resultado final es la cantidad de períodos completos que caben en el intervalo. El mensaje de advertencia alerta al usuario de que se trata de una estimación porque habrá una fracción de un período que se descarta de la respuesta. No es sensato hacer matemáticas con una fracción de un período, ya que no podemos modificar el tiempo del reloj con él a menos que lo conviertamos en múltiplos de un período más corto, pero no habrá una forma consistente de realizar la conversión. Por ejemplo, el día que mencione sería igual a 23 horas, pero otros días equivaldrían a 24 horas. Está pensando de la manera correcta: los períodos son un intento de respetar las variaciones causadas por el horario de verano, los años bisiestos, etc., pero solo lo hacen como unidades completas.

No puedo reproducir el error en la resta que mencionaste anteriormente. Parece que funciona para mí.

three <- force_tz(ymd_hms("2011-03-12 12:00:00"), "") 
    # note: here in TX, "" *is* CST 
    (four <- three + days(1)) 
    > [1] "2011-03-13 12:00:00 CDT" 
    four - days(1) 
    > [1] "2011-03-12 12:00:00 CST" 
+0

Sin embargo, para un intervalo, hay * una * forma de realizar la conversión, porque está enraizada en un instante exacto. No se sabe si un día arbitrario tiene 24 horas, pero se sabe si * este día específico * tiene 24 horas, por lo que los cálculos debería ser posible. –

+0

@KenWilliams Tomo tu punto. Lubridate actualmente no hace ese cálculo, pero tal vez debería hacerlo. Mi pensamiento ha sido que el resto podría ser 1/2 del primer día en el intervalo, pero 12/23 del último día en el intervalo. Quizás el último día es todo lo que importa. – Garrett

Cuestiones relacionadas