Quais são os formatos de “data padrão inequívoca” para a conversão de string até a data em R?

94

Por favor, considere o seguinte

$ R --vanilla

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

Mas essa data está claramente em um formato padrão não ambíguo. Por que a mensagem de erro?

Pior, uma data ambígua é aparentemente aceita sem aviso ou erro e então lida incorretamente!

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

Eu pesquisei e encontrei 28 outras questões na tag [R] contendo esta mensagem de erro. Tudo com soluções e soluções alternativas envolvendo a especificação do formato, iiuc. Esta pergunta é diferente, pois estou perguntando onde estão os formatos padrão inequívocos definidos de qualquer maneira e eles podem ser alterados? Todos recebem essas mensagens ou sou só eu? Talvez seja relacionado ao local?

Em outras palavras, existe uma solução melhor do que precisar especificar o formato?

29 questões contendo "[R] formato não ambíguo padrão"

> 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
fonte
13
a julgar pela definição da função da as.Date.characterentrada só é testado para estes dois formatos: "%Y-%m-%d"e "%Y/%m/%d". Se puder corresponder a um deles, parece ser considerado "inequívoco".
plannapus
7
@CarlWitthoft "Será que eu li" parece implicar que a resposta é incrivelmente óbvia em ?as.Date. Onde isso ajuda com isso?
Matt Dowle
2
Indiscutivelmente, "24 de janeiro de 1949" e "24 de janeiro de 1949" seriam inequívocos, mas certamente são anglo-centrados. No entanto, também existem valores para 'month.abb' que também são anglo-centrados, então um caso pode ser feito para esses valores serem correspondidos em casos onde: strptime(xx, f <- "%d $B %Y", tz = "GMT")ou strptime(xx, f <- "%B $d %Y", tz = "GMT")valores retornados. (Não estou sugerindo que month.abbseja usado para a correspondência com% B, pois os documentos dizem que a correspondência é específica do local.)
IRTFM
6
@CarlWitthoft Alguns de nós tropeçam de vez em quando. Obrigado pelo chute enquanto estou no chão. Nesta pergunta acertei algumas coisas: incluí sessionInfo (), pesquisei, contei o que pesquisei e incluí um link, mantive-o o mais consistente possível. Perdi uma linha em? As.Date e você me dá o tratamento TFM. Não podemos ser todos tão perfeitos quanto você o tempo todo.
Matt Dowle
1
@MatthewDowle, desculpe se desisti muito. Acho que a flamosidade começou quando você pareceu confundir "inequívoco para um ser humano razoavelmente bem-educado" com "inequívoco para um pedaço de código pobre e indefeso". :-(
Carl Witthoft

Respostas:

66

Este é um comportamento documentado. De ?as.Date:

formato: uma sequência de caracteres. Se não for especificado, ele tentará '"% Y-% m-% d"' então '"% Y /% m /% d"' no primeiro elemento não'NA 'e dará um erro se nenhum dos dois funcionar.

as.Date("01 Jan 2000")produz um erro porque o formato não é um dos dois listados acima. as.Date("01/01/2000")produz uma resposta incorreta porque a data não está em um dos dois formatos listados acima.

Eu considero "padrão inequívoco" como "ISO-8601" (embora as.Datenão seja tão estrito, já que "% m /% d /% Y" não é ISO-8601).

Se você receber esse erro, a solução é especificar o formato de sua data (ou horários), usando os formatos descritos em ?strptime. Tenha cuidado especial se seus dados contiverem nomes e / ou abreviações de dias / meses, pois a conversão dependerá de sua localidade (veja os exemplos em ?strptimee leia ?LC_TIME).

Joshua Ulrich
fonte
6
@BenBolker Que tal "character string is not either %Y-%m-%d or %Y/%m/%d"?
Matt Dowle
9
O comportamento certamente está documentado em ?as.Date(+1). No entanto, a mensagem de erro "formato não ambíguo padrão" é ironicamente ambígua, como atestam as 23 questões anteriores. Uma mensagem de erro mais direta como "formato não reconhecido, consulte a documentação" pode melhorar a experiência do usuário. Além disso, não acredito que "01/01/2000" seja ISO-8601 ("2000-01-01" é ISO-8601), o que aumenta a ambiguidade.
jthetzel
@jthetzel: você está certo, "01/01/2000" não é ISO-8601. Eu quis dizer que pessoalmente penso no ISO-8601 como o formato padrão e inequívoco. E eu concordo que as.Datenão reclamar de "01/01/2000" é inconsistente com a mensagem de erro.
Joshua Ulrich
31

Em outras palavras, existe uma solução melhor do que precisar especificar o formato?

Sim, existe agora (ou seja, no final de 2016), graças a anytime::anydatepartir do momento embalagem.

Veja o seguinte para alguns exemplos acima:

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

Como você disse, eles não são ambíguos e devem funcionar. E via anydate()eles fazem. Sem formato.

Dirk Eddelbuettel
fonte
2
Só vim aqui porque tínhamos outra dúvida de algo tentando analisar datas com um formato incompleto . Para completos, agora temos algo. Estou muito satisfeito com isso - era uma pergunta incômoda. E nem anytime()é preciso dizer que é igualmente útil para POSIXct.
Dirk Eddelbuettel de
Apenas usei o pacote Anytime e funcionou maravilhosamente, exceto em alguns NAs. Depois de executar trimws () no vetor data, tudo ficou perfeito.
lawyeR
Eu também uso uma tonelada!
Dirk Eddelbuettel
Parece tão simples! Eu usei anydate () em uma coluna com valores de string de mm-dd (sem aa). Todos os valores <chr> na coluna foram convertidos com êxito para <data>. Infelizmente, ele definiu o ano como '1400' em vez de '2020'. ¯_ (ツ) _ / ¯
owlstone
Bem, não exatamente. Como respondi em algumas outras perguntas neste site, mm-ddnão é uma data (nem é mm-aa ou mm-aaaa). Você não pode analisar o que não está lá.
Dirk Eddelbuettel
26

Como complemento à resposta de @JoshuaUlrich, aqui está a definição de função 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>

Então, basicamente, se strptime(x, format="%Y-%m-%d")e strptime(x, format="%Y/%m/%d")lançar um NA, é considerado ambíguo e, se não inequívoco.

Plannapus
fonte
6

Converter a data sem especificar o formato atual pode trazer esse erro para você facilmente.

Aqui está um exemplo:

sdate <- "2015.10.10"

Converta sem especificar o formato:

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

Converter com o formato especificado:

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

Isso funciona perfeitamente para mim, não importa como a data foi codificada anteriormente.

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