2011-12-13 15 views
14

tengo algunas dudas acerca de los años bisiestos, ¿cómo puedo estar seguro de que mediante el uso de una fórmula como esta¿Cómo contabilizar los años bisiestos?

add.years= function(x,y){  
if(!isTRUE(all.equal(y,round(y)))) stop("Argument \"y\" must be an integer.\n") 
x <- as.POSIXlt(x) 
x$year <- x$year+y 
as.Date(x) 
} 

tendrá en años bisiestos, al añadir, por ejemplo, 100 años a mi conjunto de datos de observación? ¿Cómo puedo controlar esto?

que tienen un conjunto de datos de series de tiempo con 50 años de observaciones:

date obs 
1995-01-01 1.0 
1995-01-02 2.0 
1995-01-03 2.5 
... 
2045-12-30 0.2 
2045-12-31 0.1 

conjunto de datos + 100 años

date obs 
2095-01-01 1.0 
2095-01-02 2.0 
2095-01-03 2.5 
... 
2145-12-30 0.2 
2145-12-31 0.1 

Después de una comprobación básica, me he dado cuenta de que el número de filas es el lo mismo para el original y 100 años después del conjunto de datos. No estoy seguro si lo que estaba antes del 29 de febrero en un año bisiesto será ahora el valor obs para el 1 de marzo en un año no bisiesto, etc.

Puedo verificar los años bisiestos usando la chronoteca la función leap.year, sin embargo, me gustaría saber si existe una forma más sencilla de hacerlo, para asegurarme de que las filas con los días del 29 de febrero que no existen 100 años después se eliminarán y los días nuevos del 29 de febrero se agregan los valores de NA.

+2

La mezcla de los formatos 'POSIXlt' y' Date' solo terminará en errores y desgarros oscuros. –

+0

¡Confirmo! Mejor pasar un tiempo para limpiar mi código. ¡Gracias! –

Respuesta

13

Puede verificar si un año es bisiesto con leap_year de lubridate.

years <- 1895:2005 
years[leap_year(years)] 

Este paquete también se encargará de no generar imposibles 29 de febrero.

ymd("2000-2-29") + years(1) # NA 
ymd("2000-2-29") %m+% years(1) # "2001-02-28" 

El "añadir meses" operador %m+%, como se ha mencionado por @VitoshKa, rollos de la fecha de regreso al final del mes anterior si no existe el día actual.

+0

'lubridate' ya no parece poder manejarlo. Obtengo 'NA' cuando intento agregar un año a un día bisiesto. – rrs

+1

El comportamiento en lubridate ha cambiado hace bastante tiempo. Obtendrá NA en fechas inválidas. Consulte el documento de [% m +%] (http://finzi.psych.upenn.edu/library/lubridate/html/mplus.html) si desea un comportamiento de desplazamiento. También documenta para 'period' y' Period-Class'. – VitoshKa

3

Un año es un año bisiesto si:

  • es divisible por 4.
  • No si es divisible por 100.
  • Pero es si es divisible por 400.

Es por eso que 2000 fue un año bisiesto (aunque es divisible por 100, también es divisible por 400).

Pero en general, si tiene una biblioteca que puede realizar cálculos de fecha/hora, úsela. Es muy complicado hacer estos cálculos y es fácil equivocarse, especialmente con las fechas antiguas (reformas del calendario) y las zonas horarias involucradas.

+0

Todavía no encuentro ninguna función que me permita hacer este tipo de modificaciones en un conjunto de datos, supongo que tengo que crear uno solo. –

+0

No, no es así. Existe una funcionalidad existente en la base R, así como en los paquetes CRAN. –

+0

Toby Marthews-3 proporciona una declaración prolija 'ifelse' para manejar años bisiestos aquí: http://r.789695.n4.nabble.com/leap-year-and-order-function-td3248104.html –

1

Sus sospechas son de hecho correcta:

x <- as.POSIXlt("2000-02-29") 
y <- x 
y$year <- y$year+100 
y 
#[1] "2100-03-01" 

Lo extraño es que otras partes del y permanecen sin cambios por lo que no puede utilizar éstos para la comparación:

y$mday 
#[1] 29 
y$mon 
#[1] 1 

pero se puede utilizar strftime :

strftime(x,"%d") 
#[1] "29" 
strftime(y,"%d") 
#[1] "01" 

¿Qué tal:

add.years <- function(x,y){ 
    if(!isTRUE(all.equal(y,round(y)))) stop("Argument \"y\" must be an integer.\n") 
    x.out <- as.POSIXlt(x) 
    x.out$year <- x.out$year+y 
    ifelse(strftime(x,"%d")==strftime(x.out,"%d"),as.Date(x.out),NA) 
    } 

continuación Puede un subconjunto de sus datos mediante [ y is.na para deshacerse de los duplicados de otro modo 1ras fechas de marzo. Aunque como estas fechas parecen ser consecutivas, es posible que desee considerar una solución que use seq.Date y evite descartar datos.

+2

2100 no es un año bisiesto, entonces el cálculo en tu primer ejemplo me parece correcto. –

Cuestiones relacionadas