รูปแบบ“ วันที่ที่ไม่คลุมเครือมาตรฐาน” สำหรับการแปลงสตริงถึงวันที่ใน R คืออะไร


94

โปรดพิจารณาสิ่งต่อไปนี้

$ R --vanilla

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

แต่วันที่นั้นอยู่ในรูปแบบมาตรฐานที่ไม่คลุมเครือ ทำไมข้อความแสดงข้อผิดพลาด?

ที่แย่กว่านั้นคือยอมรับวันที่คลุมเครือโดยไม่มีคำเตือนหรือข้อผิดพลาดและอ่านไม่ถูกต้อง!

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

ฉันได้ค้นหาและพบคำถามอีก 28 ข้อในแท็ก [R] ที่มีข้อความแสดงข้อผิดพลาดนี้ ทั้งหมดนี้มีโซลูชันและวิธีแก้ปัญหาที่เกี่ยวข้องกับการระบุรูปแบบ iiuc คำถามนี้แตกต่างจากที่ฉันถามว่ารูปแบบมาตรฐานที่ไม่คลุมเครือถูกกำหนดไว้ที่ใดแล้วและสามารถเปลี่ยนแปลงได้หรือไม่ ทุกคนได้รับข้อความเหล่านี้หรือเป็นเพียงฉัน? บางทีมันอาจเกี่ยวข้องกับสถานที่?

กล่าวอีกนัยหนึ่งมีทางออกที่ดีกว่าการต้องระบุรูปแบบหรือไม่?

29 คำถามที่ประกอบด้วย "[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

13
การตัดสินโดยนิยามฟังก์ชันของas.Date.characterอินพุตจะถูกทดสอบสำหรับสองรูปแบบนี้เท่านั้น: "%Y-%m-%d"และ"%Y/%m/%d". หากสามารถจับคู่หนึ่งในนั้นได้ดูเหมือนว่า "ไม่คลุมเครือ"
plannapus

7
@CarlWitthoft "ฉันอ่านแล้วหรือยัง" ดูเหมือนจะบ่งบอกถึงคำตอบที่ชัดเจนใน?as.Date. มันช่วยเรื่องนี้ได้ที่ไหน?
Matt Dowle

2
"24 ม.ค. 2492" และ "24 ม.ค. 2492" อาจไม่ชัดเจน แต่แน่นอนว่ามีแองโกลเป็นศูนย์กลาง นอกจากนี้ยังมีค่าสำหรับ "month.abb" ที่มี Anglo-centric ด้วยดังนั้นจึงสามารถกำหนดกรณีเพื่อให้ค่าเหล่านั้นจับคู่ได้ในกรณีที่: strptime(xx, f <- "%d $B %Y", tz = "GMT")หรือstrptime(xx, f <- "%B $d %Y", tz = "GMT")ส่งคืนค่า (ฉันไม่ได้หมายความว่าmonth.abbจะใช้สำหรับการจับคู่กับ% B เนื่องจากเอกสารบอกว่าการจับคู่เป็นภาษาเฉพาะ)
IRTFM

6
@CarlWitthoft พวกเราบางคนเดินทางขึ้นทุกครั้งแล้วครั้งเล่า ขอบคุณสำหรับการเตะในขณะที่ฉันล้มลง ในคำถามนี้ฉันมีบางสิ่งที่ถูกต้อง: ฉันรวม sessionInfo () ฉันค้นหาบอกคุณสิ่งที่ฉันค้นหาและรวมลิงค์ฉันเก็บไว้อย่างรัดกุมที่สุด ฉันพลาดหนึ่งบรรทัดในวันที่และคุณให้การรักษา TFM กับฉัน เราทุกคนไม่สามารถสมบูรณ์แบบเหมือนคุณได้ตลอดเวลา
Matt Dowle

1
@MatthewDowle ขอโทษถ้าฉันลงมายาก ฉันคิดว่าความร้อนแรงเริ่มต้นขึ้นเมื่อคุณดูเหมือนจะสร้างความสับสนให้กับ "มนุษย์ที่มีการศึกษาดีพอสมควร" กับ "ความคลุมเครือกับรหัสที่ทำอะไรไม่ถูก" :-(
Carl Witthoft

คำตอบ:


66

นี่คือพฤติกรรมที่บันทึกไว้ จาก?as.Date:

รูปแบบ: สตริงอักขระ หากไม่ได้ระบุไว้ระบบจะลอง "% Y-% m-% d" "ตามด้วย"% Y /% m /% d "" ในองค์ประกอบแรกที่ไม่ใช่ "NA "และให้ข้อผิดพลาดหากไม่ทำงาน

as.Date("01 Jan 2000")ทำให้เกิดข้อผิดพลาดเนื่องจากรูปแบบไม่ใช่หนึ่งในสองรายการข้างต้น as.Date("01/01/2000")ให้คำตอบที่ไม่ถูกต้องเนื่องจากวันที่ไม่ได้อยู่ในรูปแบบหนึ่งในสองรูปแบบที่ระบุไว้ข้างต้น

ฉันใช้ "มาตรฐานไม่คลุมเครือ" เพื่อหมายถึง "ISO-8601" (แม้ว่าas.Dateจะไม่เข้มงวดขนาดนั้นก็ตามเนื่องจาก "% m /% d /% Y" ไม่ใช่ ISO-8601)

ถ้าคุณได้รับข้อผิดพลาดนี้แก้ปัญหาคือการระบุรูปแบบวันที่ของคุณ (หรือ datetimes) ?strptimeอยู่ในการใช้รูปแบบที่อธิบายไว้ใน อย่าลืมใช้ความระมัดระวังเป็นพิเศษหากข้อมูลของคุณมีชื่อวัน / เดือนและ / หรือตัวย่อเนื่องจากการแปลงจะขึ้นอยู่กับสถานที่ของคุณ (ดูตัวอย่างใน?strptimeและอ่าน?LC_TIME)


6
@BenBolker แล้วไง"character string is not either %Y-%m-%d or %Y/%m/%d"?
Matt Dowle

9
พฤติกรรมนี้ได้รับการบันทึกไว้อย่างแน่นอนใน?as.Date(+1) อย่างไรก็ตามข้อความแสดงข้อผิดพลาด "รูปแบบมาตรฐานที่ไม่คลุมเครือ" มีความคลุมเครืออย่างน่าขันซึ่ง 23 คำถามก่อนหน้านี้เป็นเครื่องยืนยัน ข้อความแสดงข้อผิดพลาดโดยตรงเช่น "ไม่รู้จักรูปแบบโปรดดูเอกสารประกอบ" อาจช่วยปรับปรุงประสบการณ์ของผู้ใช้ นอกจากนี้ฉันไม่เชื่อว่า "01/01/2000" คือ ISO-8601 ("2000-01-01" คือ ISO-8601) ซึ่งเพิ่มความคลุมเครือ
jthetzel

@jthetzel: คุณพูดถูก "01/01/2000" ไม่ใช่ ISO-8601 ฉันหมายความว่าโดยส่วนตัวแล้วฉันคิดว่า ISO-8601 เป็นรูปแบบมาตรฐานที่ไม่คลุมเครือ และฉันยอมรับว่าการas.Dateไม่บ่นเกี่ยวกับ "01/01/2000" ไม่สอดคล้องกับข้อความแสดงข้อผิดพลาด
Joshua Ulrich

31

กล่าวอีกนัยหนึ่งมีทางออกที่ดีกว่าการต้องระบุรูปแบบหรือไม่?

ใช่ตอนนี้มีแล้ว (คือปลายปี 2559) ขอบคุณanytime::anydateจากแพ็คเกจทุกที่ทุกเวลา

ดูตัวอย่างต่อไปนี้จากด้านบน:

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

ดังที่คุณกล่าวไว้สิ่งเหล่านี้ไม่คลุมเครือและควรใช้งานได้จริง และผ่านทางanydate()พวกเขาทำ ไม่มีรูปแบบ.


2
มาที่นี่เพียงเพราะเรามีคำถามอื่นเกี่ยวกับบางสิ่งที่พยายามแยกวิเคราะห์วันที่ด้วยรูปแบบที่ไม่สมบูรณ์ สำหรับสิ่งที่สมบูรณ์ตอนนี้เรามีบางอย่าง ฉันค่อนข้างพอใจกับสิ่งนี้ - มันเป็นคำถามที่จู้จี้ และไม่มีความจำเป็นที่จะบอกว่าเป็นประโยชน์อย่างเท่าเทียมกันสำหรับanytime() POSIXct
Dirk Eddelbuettel

เพิ่งใช้แพ็คเกจทุกที่ทุกเวลาและทำงานได้อย่างยอดเยี่ยมยกเว้น NAs ไม่กี่ตัว หลังจากที่ฉันใช้ trimws () บนเวกเตอร์วันที่ทุกอย่างสมบูรณ์แบบ
lawyeR

ฉันใช้มันเป็นตันด้วย!
Dirk Eddelbuettel

ดูง่ายมาก! ฉันใช้ anydate () ในคอลัมน์ที่มีค่าสตริงเป็น mm-dd (ไม่ใช่ yy) ค่า <chr> ทั้งหมดในคอลัมน์ถูกแปลงเป็น <วันที่> เรียบร้อยแล้ว น่าเสียดายที่ตั้งปีเป็น '1400' แทนที่จะเป็น '2020' ¯_ (ツ) _ / ¯
owlstone

ก็ไม่เชิง ตามที่ฉันตอบในคำถามอื่น ๆ สองสามข้อในไซต์mm-ddนี้ไม่ใช่วันที่ (ไม่ใช่ mm-yy หรือ mm-yyyy) คุณไม่สามารถแยกวิเคราะห์สิ่งที่ไม่มีอยู่
Dirk Eddelbuettel

26

เพื่อเป็นส่วนเสริมของคำตอบของ @JoshuaUlrich นี่คือคำจำกัดความของฟังก์ชัน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>

ดังนั้นโดยพื้นฐานแล้วถ้าทั้งสองอย่างstrptime(x, format="%Y-%m-%d")และstrptime(x, format="%Y/%m/%d")โยนNAมันถือว่าคลุมเครือและถ้าไม่คลุมเครือ


6

การแปลงวันที่โดยไม่ระบุรูปแบบปัจจุบันอาจทำให้เกิดข้อผิดพลาดนี้ได้อย่างง่ายดาย

นี่คือตัวอย่าง:

sdate <- "2015.10.10"

แปลงโดยไม่ระบุรูปแบบ:

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

แปลงด้วยรูปแบบที่ระบุ:

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

2

สิ่งนี้ใช้งานได้ดีสำหรับฉันไม่ว่าวันที่จะถูกเข้ารหัสไว้ก่อนหน้านี้อย่างไร

library(lubridate)
data$created_date1 <- mdy_hm(data$created_at)
data$created_date1 <- as.Date(data$created_date1)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.