¿Cuáles son los formatos de “fecha estándar inequívoca” para la conversión de cadena a fecha en R?

93

Por favor considere lo siguiente

$ R --vanilla

> as.Date("01 Jan 2000")
Error in charToDate(x) :
    character string is not in a standard unambiguous format

Pero esa fecha claramente está en un formato estándar inequívoco. ¿Por qué el mensaje de error?

Peor aún, una fecha ambigua aparentemente se acepta sin advertencia ni error y luego se lee incorrectamente.

> as.Date("01/01/2000")
[1] "0001-01-20"

He buscado y encontrado otras 28 preguntas en la etiqueta [R] que contienen este mensaje de error. Todo con soluciones y soluciones alternativas que implican especificar el formato, iiuc. Esta pregunta es diferente porque estoy preguntando dónde se definen los formatos estándar inequívocos de todos modos, y ¿se pueden cambiar? ¿Todos reciben estos mensajes o soy solo yo? ¿Quizás esté relacionado con la configuración regional?

En otras palabras, ¿hay una solución mejor que tener que especificar el formato?

29 preguntas que contienen "[R] formato estándar sin ambigüedades"

> sessionInfo()
R version 2.15.2 (2012-10-26)
Platform: x86_64-w64-mingw32/x64 (64-bit)

locale:
[1] LC_COLLATE=English_United Kingdom.1252
[2] LC_CTYPE=English_United Kingdom.1252
[3] LC_MONETARY=English_United Kingdom.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United Kingdom.1252

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base
Matt Dowle
fuente
13
a juzgar por la definición de función de as.Date.characterla entrada, solo se prueba para estos dos formatos: "%Y-%m-%d"y "%Y/%m/%d". Si puede coincidir con uno de ellos, parece que se considera "inequívoco".
plannapus
7
@CarlWitthoft "Did I even read" parece implicar que la respuesta es deslumbrantemente obvia en ?as.Date. ¿Dónde ayuda con esto?
Matt Dowle
2
Podría decirse que "24 de enero de 1949" y "24 de enero de 1949" no serían ambiguos, pero ciertamente son anglocéntricos. Sin embargo, también hay valores para 'month.abb' que también son anglocéntricos, por lo que se podría hacer un caso para que esos valores coincidan en los casos en que: strptime(xx, f <- "%d $B %Y", tz = "GMT")o strptime(xx, f <- "%B $d %Y", tz = "GMT")valores devueltos. (No estoy insinuando que month.abbse use para la coincidencia con% B, ya que los documentos dicen que la coincidencia es específica de la configuración regional).
IRTFM
6
@CarlWitthoft Algunos de nosotros tropezamos de vez en cuando. Gracias por la patada mientras estoy abajo. En esta pregunta hice algunas cosas bien: incluí sessionInfo (), busqué, les dije lo que busqué e incluí un enlace, lo mantuve lo más coherente posible. Me perdí una línea en? As.Date y me das el tratamiento TFM. No todos podemos ser tan perfectos como tú todo el tiempo.
Matt Dowle
1
@MatthewDowle lo siento si bajé fuerte. Creo que la flamosidad comenzó cuando parecías confundir "inequívoco para un ser humano razonablemente bien educado" con "inequívoco para un pobre código indefenso". :-(
Carl Witthoft

Respuestas:

66

Este es un comportamiento documentado. De ?as.Date:

formato: una cadena de caracteres. Si no se especifica, intentará '"% Y-% m-% d"' luego '"% Y /% m /% d"' en el primer elemento que no sea'NA 'y dará un error si ninguno de los dos funciona.

as.Date("01 Jan 2000")produce un error porque el formato no es uno de los dos enumerados anteriormente. as.Date("01/01/2000")da una respuesta incorrecta porque la fecha no está en uno de los dos formatos enumerados anteriormente.

Considero que "estándar no ambiguo" significa "ISO-8601" (aunque as.Dateno es tan estricto, ya que "% m /% d /% Y" no es ISO-8601).

Si recibe este error, la solución es especificar el formato en el que se encuentran su fecha (o fecha y hora), utilizando los formatos descritos en ?strptime. Asegúrese de tener especial cuidado si sus datos contienen nombres de días / meses y / o abreviaturas, ya que la conversión dependerá de su ubicación (vea los ejemplos en ?strptimey lea ?LC_TIME).

Joshua Ulrich
fuente
6
@BenBolker ¿Qué tal "character string is not either %Y-%m-%d or %Y/%m/%d"?
Matt Dowle
9
El comportamiento ciertamente está documentado en ?as.Date(+1). Sin embargo, el mensaje de error "formato estándar sin ambigüedades" es irónicamente ambiguo, como lo atestiguan las 23 preguntas anteriores. Un mensaje de error más directo como "formato no reconocido, ver documentación" podría mejorar la experiencia del usuario. Además, no creo que "01/01/2000" sea ISO-8601 ("2000-01-01" es ISO-8601), lo que aumenta la ambigüedad.
jthetzel
@jthetzel: tienes razón, "01/01/2000" no es ISO-8601. Quise decir que personalmente creo que ISO-8601 es el formato estándar e inequívoco. Y estoy de acuerdo en que as.Dateno quejarse de "01/01/2000" es incompatible con el mensaje de error.
Joshua Ulrich
31

En otras palabras, ¿hay una solución mejor que tener que especificar el formato?

Sí, hay ahora (es decir, a finales de 2016), gracias a anytime::anydatedesde el momento paquete.

Consulte lo siguiente para ver algunos ejemplos anteriores:

R> anydate(c("01 Jan 2000", "01/01/2000", "2015/10/10"))
[1] "2000-01-01" "2000-01-01" "2015-10-10"
R> 

Como dijiste, estos son de hecho inequívocos y deberían funcionar. Y a través de anydate()ellos lo hacen. Sin formato.

Dirk Eddelbuettel
fuente
2
Solo vine aquí porque teníamos otra pregunta sobre algo que intentaba analizar las fechas con un formato incompleto . Para los completos, ahora tenemos algo. Estoy bastante satisfecho con esto, era una pregunta molesta. Y no hace falta decir que anytime()es igualmente útil para POSIXct.
Dirk Eddelbuettel
Solo usé el paquete en cualquier momento y funcionó de maravilla, excepto algunos NA. Después de ejecutar trimws () en el vector de fecha, todo fue perfecto.
abogado
¡Yo también lo uso una tonelada métrica!
Dirk Eddelbuettel
¡Parece tan simple! Usé anydate () en una columna con valores de cadena de mm-dd (no aa). Todos los valores de <chr> de la columna se convirtieron correctamente a <fecha>. Desafortunadamente, estableció el año en '1400' en lugar de '2020'. ¯_ (ツ) _ / ¯
owlstone
Bueno, no del todo. Como respondí en algunas otras preguntas en este sitio, mm-ddno es una fecha (ni mm-aa ni mm-aaaa). No puede analizar lo que no está allí.
Dirk Eddelbuettel
26

Como complemento a la respuesta de @JoshuaUlrich, aquí está la definición de función as.Date.character:

as.Date.character
function (x, format = "", ...) 
{
    charToDate <- function(x) {
        xx <- x[1L]
        if (is.na(xx)) {
            j <- 1L
            while (is.na(xx) && (j <- j + 1L) <= length(x)) xx <- x[j]
            if (is.na(xx)) 
                f <- "%Y-%m-%d"
        }
        if (is.na(xx) || !is.na(strptime(xx, f <- "%Y-%m-%d", 
            tz = "GMT")) || !is.na(strptime(xx, f <- "%Y/%m/%d", 
            tz = "GMT"))) 
            return(strptime(x, f))
        stop("character string is not in a standard unambiguous format")
    }
    res <- if (missing(format)) 
        charToDate(x)
    else strptime(x, format, tz = "GMT")
    as.Date(res)
}
<bytecode: 0x265b0ec>
<environment: namespace:base>

Entonces, básicamente, si ambos strptime(x, format="%Y-%m-%d")y strptime(x, format="%Y/%m/%d")arrojan un NA, se considera ambiguo y, si no, inequívoco.

plannapus
fuente
6

Convertir la fecha sin especificar el formato actual puede traerle este error fácilmente.

Aquí hay un ejemplo:

sdate <- "2015.10.10"

Convertir sin especificar el formato:

date <- as.Date(sdate4) # ==> This will generate the same error"""Error in charToDate(x): character string is not in a standard unambiguous format""".

Convertir con formato especificado:

date <- as.Date(sdate4, format = "%Y.%m.%d") # ==> Error Free Date Conversion.
HassanSh__3571619
fuente
2

Esto funciona perfectamente para mí, sin importar cómo se codificó la fecha anteriormente.

library(lubridate)
data$created_date1 <- mdy_hm(data$created_at)
data$created_date1 <- as.Date(data$created_date1)
Viviana Wu
fuente