Định dạng "ngày rõ ràng tiêu chuẩn" để chuyển đổi chuỗi thành ngày trong R là gì?


94

Vui lòng xem xét những điều sau

$ R --vanilla

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

Nhưng ngày đó rõ ràng ở định dạng rõ ràng tiêu chuẩn. Tại sao thông báo lỗi?

Tệ hơn, một ngày không rõ ràng dường như được chấp nhận mà không có cảnh báo hoặc lỗi và sau đó đọc sai!

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

Tôi đã tìm kiếm và tìm thấy 28 câu hỏi khác trong thẻ [R] có chứa thông báo lỗi này. Tất cả đều có các giải pháp và cách giải quyết liên quan đến việc chỉ định định dạng, iiuc. Câu hỏi này khác ở chỗ tôi đang hỏi đâu là định dạng rõ ràng tiêu chuẩn được xác định và chúng có thể thay đổi được không? Mọi người có nhận được những tin nhắn này không hay chỉ tôi với? Có lẽ nó liên quan đến ngôn ngữ?

Nói cách khác, có giải pháp nào tốt hơn là cần chỉ định định dạng không?

29 câu hỏi có chứa "[R] định dạng rõ ràng chuẩn"

> 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
đánh giá theo định nghĩa chức năng của as.Date.characterđầu vào chỉ được kiểm tra cho hai định dạng sau: "%Y-%m-%d""%Y/%m/%d". Nếu nó có thể khớp với một trong số chúng thì nó có vẻ được coi là "rõ ràng".
plannapus

7
@CarlWitthoft "Tôi thậm chí đã đọc" dường như ngụ ý rằng câu trả lời là rõ ràng rõ ràng ?as.Date. Nó giúp được gì cho việc này?
Matt Dowle

2
Có thể cho rằng "ngày 24 tháng 1 năm 1949" và "ngày 24 tháng 1 năm 1949" sẽ không rõ ràng, nhưng chúng chắc chắn là trung tâm của Anh. Tuy nhiên, cũng có các giá trị cho 'month.abb' cũng là Anglo-centric, vì vậy có thể tạo ra một trường hợp để các giá trị đó được khớp trong trường hợp: strptime(xx, f <- "%d $B %Y", tz = "GMT")hoặc strptime(xx, f <- "%B $d %Y", tz = "GMT")các giá trị được trả về. (Tôi không ngụ ý rằng điều đó month.abbđược sử dụng để đối sánh với% B vì tài liệu nói rằng đối sánh là ngôn ngữ cụ thể.)
IRTFM

6
@CarlWitthoft Một số người trong chúng ta thỉnh thoảng đi lại. Cảm ơn vì cú đá trong khi tôi thất vọng. Trong câu hỏi này, tôi có một số điều đúng: Tôi đã bao gồm sessionInfo (), tôi đã tìm kiếm, cho bạn biết những gì tôi đã tìm kiếm và bao gồm một liên kết, tôi giữ nó càng kỹ càng tốt. Tôi đã bỏ lỡ một dòng trong? As.Date và bạn cho tôi điều trị TFM. Tất cả chúng ta không thể hoàn hảo như bạn mọi lúc.
Matt Dowle

1
@MatthewDowle xin lỗi nếu tôi xuống khó. Tôi nghĩ rằng sự bối rối bắt đầu khi bạn dường như nhầm lẫn giữa "rõ ràng với một con người được giáo dục tốt" với "rõ ràng là một mã nghèo không nơi nương tựa". :-(
Carl Witthoft

Câu trả lời:


66

Đây là hành vi được ghi lại. Từ ?as.Date:

định dạng: Một chuỗi ký tự. Nếu không được chỉ định, nó sẽ thử '"% Y-% m-% d"' rồi '"% Y /% m /% d"' trên phần tử không phải'NA 'đầu tiên và đưa ra lỗi nếu cả hai đều không hoạt động.

as.Date("01 Jan 2000")dẫn đến lỗi vì định dạng không phải là một trong hai định dạng được liệt kê ở trên. as.Date("01/01/2000")đưa ra câu trả lời không chính xác vì ngày tháng không thuộc một trong hai định dạng được liệt kê ở trên.

Tôi lấy "tiêu chuẩn rõ ràng" có nghĩa là "ISO-8601" (mặc dù as.Datekhông nghiêm ngặt như vậy, vì "% m /% d /% Y" không phải là ISO-8601).

Nếu bạn nhận được lỗi này, giải pháp là chỉ định định dạng ngày (hoặc ngày giờ) của bạn, sử dụng các định dạng được mô tả trong ?strptime. Hãy chắc chắn sử dụng cẩn thận nếu dữ liệu của bạn chứa tên ngày / tháng và / hoặc chữ viết tắt, vì chuyển đổi sẽ phụ thuộc vào ngôn ngữ của bạn (xem các ví dụ trong ?strptimevà đọc ?LC_TIME).


6
@BenBolker Làm thế nào về "character string is not either %Y-%m-%d or %Y/%m/%d"?
Matt Dowle

9
Hành vi chắc chắn được ghi lại trong ?as.Date(+1). Tuy nhiên, thông báo lỗi "định dạng rõ ràng tiêu chuẩn" lại rất mơ hồ, mà 23 câu hỏi trước đó đã chứng thực. Thông báo lỗi trực tiếp hơn như "không nhận dạng được định dạng, hãy xem tài liệu" có thể cải thiện trải nghiệm người dùng. Ngoài ra, tôi không tin "01/01/2000" là ISO-8601 ("2000-01-01" là ISO-8601), điều này làm tăng thêm sự mơ hồ.
jthetzel

@jthetzel: bạn nói đúng, "01/01/2000" không phải là ISO-8601. Ý tôi là cá nhân tôi nghĩ ISO-8601 là định dạng tiêu chuẩn, rõ ràng. Và tôi đồng ý rằng việc as.Datekhông phàn nàn về "01/01/2000" là không phù hợp với thông báo lỗi.
Joshua Ulrich

31

Nói cách khác, có giải pháp nào tốt hơn là cần chỉ định định dạng không?

Vâng, bây giờ có (tức là vào cuối năm 2016), nhờ vào anytime::anydatetừ bất cứ lúc nào gói.

Xem phần sau để biết một số ví dụ từ trên:

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

Như bạn đã nói, những điều này trên thực tế không rõ ràng và chỉ nên hoạt động. Và thông qua anydate()họ làm. Không có định dạng.


2
Chỉ đến đây vì chúng tôi có một câu hỏi khác về điều gì đó đang cố gắng phân tích cú pháp ngày tháng với định dạng không hoàn chỉnh . Đối với những cái hoàn chỉnh, bây giờ chúng tôi có một cái gì đó. Tôi khá hài lòng với điều này - đó là một câu hỏi dai dẳng. Và không cần phải nói, anytime()cũng hữu ích cho POSIXct.
Dirk Eddelbuettel

Chỉ cần sử dụng gói bất cứ lúc nào và nó hoạt động tuyệt vời, ngoại trừ một số NA. Sau khi tôi chạy trimws () trên vector ngày, mọi thứ đều hoàn hảo.
lawyeR

Tôi cũng sử dụng nó một tấn!
Dirk Eddelbuettel

Trông thật đơn giản! Tôi đã sử dụng anydate () trên một cột có giá trị chuỗi là mm-dd (không có yy). Tất cả các giá trị <chr> trong cột đã được chuyển đổi thành công thành <ngày>. Thật không may, nó đã đặt năm thành '1400' thay vì '2020'. ¯_ (ツ) _ / ¯
owlstone

Chà, không hoàn toàn. Như tôi đã trả lời trong một số câu hỏi khác trên trang web này, mm-ddkhông phải là ngày tháng (mm-yy hay mm-yyyy). Bạn không thể phân tích cú pháp những gì nó không có ở đó.
Dirk Eddelbuettel

26

Để bổ sung cho câu trả lời @JoshuaUlrich, đây là định nghĩa của hà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>

Vì vậy, về cơ bản nếu cả hai strptime(x, format="%Y-%m-%d")strptime(x, format="%Y/%m/%d")ném một NAthì nó được coi là mơ hồ và nếu không nói là rõ ràng.


6

Việc chuyển đổi ngày tháng mà không chỉ định định dạng hiện tại có thể dễ gây ra lỗi này cho bạn.

Đây là một ví dụ:

sdate <- "2015.10.10"

Chuyển đổi mà không chỉ định Định dạng:

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

Chuyển đổi với Định dạng được chỉ định:

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

2

Điều này hoạt động hoàn hảo đối với tôi, không quan trọng ngày trước đó được mã hóa như thế nào.

library(lubridate)
data$created_date1 <- mdy_hm(data$created_at)
data$created_date1 <- as.Date(data$created_date1)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.