R'de dizeden bugüne kadar olan dönüştürme için "standart kesin tarih" biçimleri nelerdir?


94

Lütfen aşağıdakileri dikkate alın

$ R --vanilla

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

Ama bu tarih açıkça olan standart bir açık biçimde. Neden hata mesajı?

Daha da kötüsü, belirsiz bir tarih görünürde herhangi bir uyarı veya hata olmaksızın kabul edilir ve sonra yanlış okunur!

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

Bu hata mesajını içeren [R] etiketinde başka 28 soru aradım ve buldum. Tümü, formatı belirtmeyi içeren çözümler ve geçici çözümler ile iiuc. Bu soru farklı, çünkü ben soruyorum standart kesin olmayan biçimler zaten tanımlanmış ve değiştirilebilir mi? Herkes bu mesajları alıyor mu yoksa sadece ben miyim? Belki yerel ile ilgilidir?

Başka bir deyişle, formatı belirlemekten daha iyi bir çözüm var mı?

"[R] standart kesin biçim" içeren 29 soru

> 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
as.Date.charactergirdinin işlev tanımına göre değerlendirme yalnızca şu iki format için test edilir: "%Y-%m-%d"ve "%Y/%m/%d". Bunlardan biriyle eşleşebiliyorsa, "belirsiz" kabul edilir.
plannapus

7
@CarlWitthoft "Okudum mu?" Cevabın göze çarpacak kadar açık olduğunu gösteriyor ?as.Date. Bununla nereye yardımcı olur?
Matt Dowle

2
Muhtemelen "24 Ocak 1949" ve "24 Ocak 1949" açık olacaktır, ancak kesinlikle Anglo-merkezlidirler. Yine de 'month.abb' için Anglo merkezli değerler de vardır, bu nedenle: strptime(xx, f <- "%d $B %Y", tz = "GMT")veya strptime(xx, f <- "%B $d %Y", tz = "GMT")değerlerin döndürüldüğü durumlarda bu değerlerin eşleşmesi için bir durum yapılabilir . ( month.abbDokümanlar
eşleşmenin

6
@CarlWitthoft Bazılarımız arada bir ayağa kalkarız. Ben yerdeyken tekme için teşekkürler. Bu soruda birkaç şeyi doğru anladım: sessionInfo () 'yu ekledim, araştırdım, ne aradığımı söyledim ve bir bağlantı ekledim, mümkün olduğunca akılda tuttum. Tarihin bir satırını kaçırdım ve bana TFM tedavisini veriyorsun. Hepimiz her zaman senin kadar mükemmel olamayız.
Matt Dowle

1
@MatthewDowle eğer sert geldiysem üzgünüm. Sanırım alevlenme, "makul derecede iyi eğitimli bir insan için kesin olan" ile "zayıf, çaresiz bir kod parçası" ile karıştırdığınız zaman başladı. :-(
Carl Witthoft

Yanıtlar:


66

Bu, belgelenmiş bir davranıştır. Kimden ?as.Date:

format: Bir karakter dizisi. Belirtilmezse, '"% Y-% m-% d"' ve ardından "% Y /% m /% d" 'yi' NA 'olmayan ilk öğede deneyecek ve hiçbiri çalışmazsa bir hata verecektir.

as.Date("01 Jan 2000")biçim yukarıda listelenen ikisinden biri olmadığı için hata verir. as.Date("01/01/2000")Tarih yukarıda listelenen iki biçimden birinde olmadığından yanlış bir yanıt verir.

"Standart net" i "ISO-8601" anlamına gelecek şekilde alıyorum ( as.Date"% m /% d /% Y" ISO-8601 olmadığı için o kadar katı olmasa da).

Bu hatayı alırsanız çözüm, içinde açıklanan biçimleri kullanarak tarihinizin (veya tarih saatlerinin) bulunduğu biçimi belirlemektir ?strptime. Verileriniz gün / ay isimleri ve / veya kısaltmalar içeriyorsa, özellikle dikkatli olun, çünkü dönüştürme yerel ayarınıza bağlı olacaktır (içindeki örneklere bakın ?strptimeve okuyun ?LC_TIME).


6
@BenBolker Peki ya "character string is not either %Y-%m-%d or %Y/%m/%d"?
Matt Dowle

9
Davranış kesinlikle ?as.Date(+1) olarak belgelenmiştir . Bununla birlikte, "standart kesin biçim" hata mesajı, ironik bir şekilde belirsizdir ve önceki 23 soru bunu doğrulamaktadır. "Biçim tanınmadı, belgelere bakın" gibi daha doğrudan bir hata mesajı, kullanıcı deneyimini iyileştirebilir. Ayrıca "01/01/2000" in ISO-8601 ("2000-01-01", ISO-8601) olduğuna inanmıyorum, bu da belirsizliğe katkıda bulunuyor.
jthetzel

@jthetzel: haklısınız, "01/01/2000" ISO-8601 değil. Ben şahsen ISO-8601'in standart, kesin bir format olduğunu düşündüğümü kastettim. Ve as.Date"01/01/2000" hakkında şikayet etmemenin hata mesajıyla tutarsız olduğunu kabul ediyorum .
Joshua Ulrich

31

Başka bir deyişle, formatı belirlemekten daha iyi bir çözüm var mı?

Evet, (yani geç 2016) orada şimdi, sayesinde anytime::anydategelen her paketin.

Yukarıdan bazı örnekler için aşağıdakilere bakın:

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

Dediğin gibi, bunlar aslında kesin ve işe yaramalı . Ve anydate()onlar aracılığıyla . Biçimsiz.


2
Buraya ancak tarihleri eksik bir formatla ayrıştırmaya çalışan başka bir sorumuz olduğu için geldik . Tam olanlar için artık bir şeyimiz var. Bundan oldukça memnunum - rahatsız edici bir soruydu. Ve söylemeye gerek yok, anytime()eşit derecede faydalıdır POSIXct.
Dirk Eddelbuettel

Sadece her zaman paketini kullandım ve epeyce NA dışında harika bir şekilde çalıştı. Tarih vektöründe trimws () çalıştırdıktan sonra her şey mükemmeldi.
lawyeR

Ben de bir metrik ton kullanıyorum!
Dirk Eddelbuettel

Çok basit görünüyor! Dize değerleri mm-gg (yy yok) olan bir sütunda anydate () kullandım. Sütundaki tüm <chr> değerleri başarıyla <tarih> 'e dönüştürüldü. Maalesef yılı '2020' yerine '1400' olarak belirledi. ¯_ (ツ) _ / ¯
owlstone

Pek iyi değil. Bu sitedeki birkaç soruyu daha cevapladığım gibi, mm-ddbir tarih değil (aa-yy veya aa-yyyy değil). Orada olmayan şeyi ayrıştıramazsınız.
Dirk Eddelbuettel

26

@JoshuaUlrich cevabının bir tamamlayıcısı olarak, işte fonksiyonun tanımı 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>

Yani temelde eğer hem strptime(x, format="%Y-%m-%d")ve strptime(x, format="%Y/%m/%d")atarsa NAbelirsiz ve belirsiz değilse de belirsiz kabul edilir.


6

Mevcut formatı belirtmeden tarihi dönüştürmek bu hatayı size kolayca getirebilir.

İşte bir örnek:

sdate <- "2015.10.10"

Biçimi belirtmeden dönüştürün:

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

Belirtilen Biçimle Dönüştür:

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

2

Daha önce tarih nasıl kodlanmış olursa olsun, bu benim için mükemmel çalışıyor.

library(lubridate)
data$created_date1 <- mdy_hm(data$created_at)
data$created_date1 <- as.Date(data$created_date1)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.