Quali sono i formati di "data univoca standard" per la conversione da stringa a data in R?


94

Si prega di considerare quanto segue

$ R --vanilla

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

Ma quella data è chiaramente in un formato standard non ambiguo. Perché il messaggio di errore?

Peggio ancora, una data ambigua viene apparentemente accettata senza preavviso o errore e quindi letta in modo errato!

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

Ho cercato e trovato altre 28 domande nel tag [R] contenente questo messaggio di errore. Il tutto con soluzioni e soluzioni alternative che implicano la specifica del formato, iiuc. Questa domanda è diversa in quanto sto chiedendo dove sono comunque definiti i formati standard non ambigui e possono essere modificati? Tutti ricevono questi messaggi o sono solo io? Forse è correlato alla localizzazione?

In altre parole, esiste una soluzione migliore rispetto alla necessità di specificare il formato?

29 domande contenenti "[R] formato standard non ambiguo"

> 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

13
a giudicare dalla funzione, la definizione as.Date.characterdell'input è testata solo per questi due formati: "%Y-%m-%d"e "%Y/%m/%d". Se può corrispondere a uno di essi, sembra essere considerato "non ambiguo".
plannapus

7
@CarlWitthoft "Ho anche letto" sembra implicare che la risposta sia assolutamente ovvia in ?as.Date. Dove aiuta con questo?
Matt Dowle

2
Probabilmente "24 gennaio 1949" e "24 gennaio 1949" sarebbero inequivocabili, ma sono certamente anglo-centrici. Eppure ci sono anche valori per 'month.abb' che sono anche anglo-centrici, quindi si potrebbe fare un caso per quei valori da abbinare nei casi in cui: strptime(xx, f <- "%d $B %Y", tz = "GMT")o strptime(xx, f <- "%B $d %Y", tz = "GMT")valori restituiti. (Non sto insinuando che month.abbsia utilizzato per la corrispondenza a% B poiché i documenti dicono che la corrispondenza è specifica della locale.)
IRTFM

6
@CarlWitthoft Alcuni di noi inciampano ogni tanto. Grazie per il calcio mentre sono a terra. In questa domanda ho capito un bel po 'di cose: ho incluso sessionInfo (), ho cercato, ti ho detto cosa cercavo e incluso un link, l'ho mantenuto il più coerente possibile. Ho perso una riga in data e tu mi dai il trattamento TFM. Non possiamo essere tutti perfetti come te tutto il tempo.
Matt Dowle

1
@ MatthewDowle scusa se sono venuto giù duro. Penso che la confusione sia iniziata quando sembravi confondere "non ambiguo per un umano ragionevolmente istruito" con "non ambiguo per un povero pezzo di codice indifeso". :-(
Carl Witthoft

Risposte:


66

Questo è un comportamento documentato. Da ?as.Date:

formato: una stringa di caratteri. Se non specificato, proverà '"% Y-% m-% d"' quindi '"% Y /% m /% d"' sul primo elemento non'NA 'e restituirà un errore se nessuno dei due funziona.

as.Date("01 Jan 2000")restituisce un errore perché il formato non è uno dei due sopra elencati. as.Date("01/01/2000")restituisce una risposta errata perché la data non è in uno dei due formati sopra elencati.

Prendo "standard non ambiguo" per significare "ISO-8601" (anche se as.Datenon è così rigoroso, poiché "% m /% d /% Y" non è ISO-8601).

Se ricevi questo errore, la soluzione è specificare il formato in cui si trovano la tua data (o data e ora), utilizzando i formati descritti in ?strptime. Assicurati di usare particolare attenzione se i tuoi dati contengono nomi di giorni / mesi e / o abbreviazioni, poiché la conversione dipenderà dalla tua lingua (vedi gli esempi in ?strptimee leggi ?LC_TIME).


6
@BenBolker Che ne dici "character string is not either %Y-%m-%d or %Y/%m/%d"?
Matt Dowle

9
Il comportamento è certamente documentato in ?as.Date(+1). Tuttavia, il messaggio di errore "formato standard non ambiguo" è ironicamente ambiguo, come attestano le 23 domande precedenti. Un messaggio di errore più diretto come "formato non riconosciuto, consultare la documentazione" potrebbe migliorare l'esperienza dell'utente. Inoltre, non credo che "01/01/2000" sia ISO-8601 ("2000-01-01" è ISO-8601), il che aumenta l'ambiguità.
jthetzel

@jthetzel: hai ragione, "01/01/2000" non è ISO-8601. Volevo dire che personalmente penso che ISO-8601 sia il formato standard e inequivocabile. E sono d'accordo che as.Datenon lamentarsi di "01/01/2000" non è coerente con il messaggio di errore.
Joshua Ulrich

31

In altre parole, esiste una soluzione migliore rispetto alla necessità di specificare il formato?

Sì, v'è ora (cioè a fine 2016), grazie al anytime::anydatedal momento pacchetto.

Vedere quanto segue per alcuni esempi dall'alto:

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

Come hai detto, questi sono in realtà inequivocabili e dovrebbero funzionare. E via anydate()lo fanno. Senza un formato.


2
Siamo venuti qui solo perché avevamo un'altra domanda su qualcosa che cercava di analizzare le date con un formato incompleto . Per quelli completi, ora abbiamo qualcosa. Sono abbastanza soddisfatto di questo: era una domanda fastidiosa. E inutile dirlo, anytime()è ugualmente utile per POSIXct.
Dirk Eddelbuettel

Ho appena usato il pacchetto anytime e ha funzionato meravigliosamente, tranne un bel po 'di NA. Dopo aver eseguito trimws () sul vettore della data, tutto era perfetto.
lawyeR

Lo uso anch'io una tonnellata metrica!
Dirk Eddelbuettel

Sembra così semplice! Ho usato anydate () su una colonna con valori di stringa di mm-dd (no yy). Tutti i valori <chr> nella colonna sono stati convertiti correttamente in <data>. Sfortunatamente, ha impostato l'anno su "1400" anziché su "2020". ¯_ (ツ) _ / ¯
owlstone

Beh, non proprio. Come ho risposto in poche altre domande su questo sito, mm-ddnon è una data (né lo è mm-yy o mm-yyyy). Non puoi analizzare ciò che non c'è.
Dirk Eddelbuettel

26

Come complemento alla risposta di @JoshuaUlrich, ecco la definizione di funzione 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>

Quindi fondamentalmente se entrambi strptime(x, format="%Y-%m-%d")e strptime(x, format="%Y/%m/%d")lancia un NAè considerato ambiguo e se non univoco.


6

La conversione della data senza specificare il formato corrente può portare facilmente questo errore.

Ecco un esempio:

sdate <- "2015.10.10"

Converti senza specificare il formato:

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

Converti con il formato specificato:

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

2

Questo funziona perfettamente per me, non importa come la data è stata codificata in precedenza.

library(lubridate)
data$created_date1 <- mdy_hm(data$created_at)
data$created_date1 <- as.Date(data$created_date1)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.