separar - ¿Hay alguna manera más elegante de convertir años de dos dígitos a años de cuatro dígitos con lubridate?
manipulacion de horas en r (3)
Si un vector de fecha tiene años de dos dígitos, mdy()
cambia años entre 00 y 68 en años del siglo XXI y años entre 69 y 99 en años del siglo XX. Por ejemplo:
library(lubridate)
mdy(c("1/2/54","1/2/68","1/2/69","1/2/99","1/2/04"))
da el siguiente resultado:
Multiple format matches with 5 successes: %m/%d/%y, %m/%d/%Y.
Using date format %m/%d/%y.
[1] "2054-01-02 UTC" "2068-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC" "2004-01-02 UTC"
Puedo solucionar esto después del hecho al restar 100 de las fechas incorrectas para convertir 2054 y 2068 en 1954 y 1968. Pero ¿hay un método más elegante y menos propenso a errores de analizar fechas de dos dígitos para que se manejen correctamente en el proceso de análisis en sí?
Actualización: Después de que JoshuaUlrich me indicó que strptime
, encontré esta pregunta , que trata de un problema similar al mío, pero usando la base R.
Parece que una buena adición al manejo de fechas en R sería una forma de manejar los cortes de selección de siglo para fechas de dos dígitos dentro de las funciones de análisis de fecha.
Acabo de experimentar exactamente este mismo error / función.
Terminé escribiendo las siguientes dos funciones rápidas para ayudar a convertir las fechas de tipo Excel (que es donde obtengo más) a algo que R puede usar.
No hay nada malo con la respuesta aceptada, es solo que prefiero no cargar demasiado los paquetes.
Primero, un ayudante para dividir y reemplazar los años ...
year1900 <- function(dd_y, yrFlip = 50)
{
dd_y <- as.numeric(dd_y)
dd_y[dd_y > yrFlip] <- dd_y[dd_y > yrFlip] + 1900
dd_y[dd_y < yrFlip] <- dd_y[dd_y < yrFlip] + 2000
return(dd_y)
}
que es utilizado por una función que ''arregla'' sus fechas de Excel, según el tipo:
XLdate <- function(Xd, type = ''b-Y'')
{
switch(type,
''b-Y'' = as.Date(paste0(substr(Xd, 5, 9), "-", substr(Xd, 1, 3), "-01"), format = "%Y-%b-%d"),
''b-y'' = as.Date(paste0(year1900(substr(Xd, 5, 6)), "-", substr(Xd, 1, 3), "-01"),
format = "%Y-%b-%d"),
''Y-b'' = as.Date(paste0(substr(Xd, 1, 3), "-", substr(Xd, 5, 9), "-01"), format = "%Y-%b-%d")
)
}
Espero que esto ayude.
Aquí hay una función que le permite hacer esto:
library(lubridate)
x <- mdy(c("1/2/54","1/2/68","1/2/69","1/2/99","1/2/04"))
foo <- function(x, year=1968){
m <- year(x) %% 100
year(x) <- ifelse(m > year %% 100, 1900+m, 2000+m)
x
}
Pruébalo:
x
[1] "2054-01-02 UTC" "2068-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC"
[5] "2004-01-02 UTC"
foo(x)
[1] "2054-01-02 UTC" "2068-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC"
[5] "2004-01-02 UTC"
foo(x, 1950)
[1] "1954-01-02 UTC" "1968-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC"
[5] "2004-01-02 UTC"
La parte mágica aquí es usar el operador de módulo %%
para devolver la fracción de una división. Entonces 1968 %% 100
rinde 68.
Otra opción sería:
xxx <- c("01-Jan-54","01-Feb-68","01-Aug-69","01-May-99","01-Jun-04", "
31-Dec-68","01-Jan-69", "31-Dec-99")
.
dmy(paste0(sub("//d//d$","",xxx) , ifelse( (tt <-
sub("//d//d-//D//D//D-","",xxx) ) > 20 ,paste0("19",tt),paste0("20",tt))))
Aunque ninguna solución es elegante ni corta. Creo que sería mejor si lubridate acaba de agregar una opción para especificar la fecha de corte.