Apa itu format "tanggal tidak ambigu standar" untuk konversi string-to-date di R?

94

Harap pertimbangkan hal berikut

$ R --vanilla

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

Tapi tanggal itu jelas adalah dalam format ambigu standar. Mengapa muncul pesan kesalahan?

Lebih buruk lagi, tanggal yang ambigu tampaknya diterima tanpa peringatan atau kesalahan dan kemudian salah dibaca!

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

Saya telah mencari dan menemukan 28 pertanyaan lain di tag [R] yang mengandung pesan kesalahan ini. Semua dengan solusi dan solusi yang melibatkan spesifikasi format, iiuc. Pertanyaan ini berbeda karena saya bertanya di mana format standar yang tidak ambigu didefinisikan, dan dapatkah mereka diubah? Apakah semua orang mendapatkan pesan ini atau hanya saya? Mungkin itu terkait dengan lokal?

Dengan kata lain, apakah ada solusi yang lebih baik daripada perlu menentukan format?

29 pertanyaan yang berisi "format tidak ambigu standar [R]"

> 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
sumber
13
dilihat dari definisi fungsi as.Date.characterinput hanya diuji untuk dua format ini: "%Y-%m-%d"dan "%Y/%m/%d". Jika bisa cocok dengan salah satu dari mereka tampaknya akan dianggap "tidak ambigu".
plannapus
7
@CarlWitthoft "Apakah saya bahkan membaca" tampaknya menyiratkan bahwa jawabannya sangat jelas di ?as.Date. Dimana membantu dengan ini?
Matt Dowle
2
Bisa dibilang, "24 Jan 1949" dan "24 Jan 1949" tidak ambigu, tapi jelas-jelas Anglo-sentris. Namun ada juga nilai untuk 'month.abb' yang Anglo-sentris juga, jadi kasus dapat dibuat agar nilai-nilai tersebut dicocokkan dalam kasus di mana: strptime(xx, f <- "%d $B %Y", tz = "GMT")atau strptime(xx, f <- "%B $d %Y", tz = "GMT")nilai yang dikembalikan. (Saya tidak menyiratkan bahwa month.abbdigunakan untuk pencocokan ke% B karena dokumen mengatakan pencocokan adalah khusus lokal.)
IRTFM
6
@CarlWitthoft Beberapa dari kita terkadang tersandung. Terima kasih atas tendangannya saat saya turun. Dalam pertanyaan ini saya mendapatkan beberapa hal yang benar: Saya menyertakan sessionInfo (), saya mencari, memberi tahu Anda apa yang saya cari dan menyertakan tautan, saya menyimpannya sesingkat mungkin. Saya melewatkan satu baris dalam? As. Tanggal dan Anda memberi saya perawatan TFM. Kami tidak bisa sesempurna Anda sepanjang waktu.
Matt Dowle
1
@MatthewDowle maaf jika saya turun dengan keras. Saya pikir flamositas dimulai ketika Anda tampaknya membingungkan "tidak ambigu untuk manusia yang cukup berpendidikan" dengan "tidak ambigu untuk sepotong kode yang tidak berdaya". :-(
Carl Witthoft

Jawaban:

66

Ini adalah perilaku yang didokumentasikan. Dari ?as.Date:

format: Sebuah string karakter. Jika tidak ditentukan, ini akan mencoba '"% Y-% m-% d"' lalu '"% Y /% m /% d"' pada elemen non-'NA 'pertama, dan memberikan kesalahan jika tidak ada yang berfungsi.

as.Date("01 Jan 2000")menghasilkan kesalahan karena formatnya bukan salah satu dari dua yang tercantum di atas. as.Date("01/01/2000")menghasilkan jawaban yang salah karena tanggal tidak termasuk dalam salah satu dari dua format yang tercantum di atas.

Saya mengartikan "tidak ambigu standar" sebagai "ISO-8601" (meskipun as.Datetidak seketat itu, karena "% m /% d /% Y" bukan ISO-8601).

Jika Anda menerima kesalahan ini, solusinya adalah menentukan format tanggal (atau waktu) Anda, menggunakan format yang dijelaskan di ?strptime. Pastikan untuk berhati-hati jika data Anda berisi nama hari / bulan dan / atau singkatan, karena konversi akan bergantung pada lokal Anda (lihat contoh di ?strptimedan baca ?LC_TIME).

Joshua Ulrich
sumber
6
@BenBolker Bagaimana "character string is not either %Y-%m-%d or %Y/%m/%d"?
Matt Dowle
9
Perilaku tersebut tentunya didokumentasikan dalam ?as.Date(+1). Namun, pesan kesalahan "format tidak ambigu standar" ironisnya ambigu, yang dibuktikan oleh 23 pertanyaan sebelumnya. Pesan kesalahan yang lebih langsung seperti, "format tidak dikenali, lihat dokumentasi" dapat meningkatkan pengalaman pengguna. Selain itu, saya tidak yakin "01/01/2000" adalah ISO-8601 ("2000-01-01" adalah ISO-8601), yang menambah ambiguitas.
jthetzel
@jthetzel: Anda benar, "01/01/2000" bukan ISO-8601. Maksud saya, saya pribadi menganggap ISO-8601 sebagai format standar dan tidak ambigu. Dan saya setuju bahwa as.Datetidak mengeluh tentang "01/01/2000" tidak sesuai dengan pesan kesalahan.
Joshua Ulrich
31

Dengan kata lain, apakah ada solusi yang lebih baik daripada perlu menentukan format?

Ya, sekarang ada (yaitu di akhir 2016), berkat anytime::anydatedari paket kapan saja .

Lihat yang berikut untuk beberapa contoh dari atas:

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

Seperti yang Anda katakan, ini sebenarnya tidak ambigu dan seharusnya berfungsi. Dan melalui yang anydate()mereka lakukan. Tanpa format.

Dirk Eddelbuettel
sumber
2
Hanya datang ke sini karena kami memiliki pertanyaan lain tentang sesuatu yang mencoba mengurai tanggal dengan format yang tidak lengkap . Untuk yang lengkap, sekarang kita punya sesuatu. Saya cukup senang dengan ini - itu adalah pertanyaan yang mengganggu. Dan tak perlu dikatakan, anytime()sama berguna untuk POSIXct.
Dirk Eddelbuettel
Baru saja menggunakan paket kapan saja dan itu bekerja dengan sangat baik, kecuali beberapa NA. Setelah saya menjalankan trimws () pada vektor tanggal, semuanya sempurna.
lawyeR
Saya menggunakannya juga satu metrik ton!
Dirk Eddelbuettel
Terlihat sangat sederhana! Saya menggunakan anydate () pada kolom dengan nilai string mm-dd (no yy). Semua nilai <chr> di kolom berhasil dikonversi menjadi <tanggal>. Sayangnya, ini menetapkan tahun ke '1400', bukan '2020'. ¯_ (ツ) _ / ¯
owlstone
Yah, kurang tepat. Seperti yang saya jawab dalam beberapa pertanyaan lain di situs ini, mm-ddbukanlah tanggal (bukan mm-yy atau mm-yyyy). Anda tidak dapat mengurai apa yang tidak ada.
Dirk Eddelbuettel
26

Sebagai pelengkap jawaban @JoshuaUlrich, berikut definisi fungsinya 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>

Jadi pada dasarnya jika keduanya strptime(x, format="%Y-%m-%d")dan strptime(x, format="%Y/%m/%d")melempar NAitu dianggap ambigu dan jika tidak tidak ambigu.

plannapus
sumber
6

Mengonversi tanggal tanpa menentukan format saat ini dapat membawa kesalahan ini kepada Anda dengan mudah.

Berikut ini contohnya:

sdate <- "2015.10.10"

Konversi tanpa menentukan Format:

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

Konversikan dengan Format tertentu:

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

Ini bekerja dengan sempurna untuk saya, tidak peduli bagaimana tanggal itu dikodekan sebelumnya.

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