Які існують формати “стандартних однозначних дат” для перетворення рядків на дату в 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 січня 1949 р." І "24 січня 1949 р." Було б однозначно, але вони, безумовно, англоцентричні. Проте існують також значення для 'month.abb', які також є англоцентричними, тому може бути зроблений випадок, щоб ці значення відповідали у випадках, коли: strptime(xx, f <- "%d $B %Y", tz = "GMT")або strptime(xx, f <- "%B $d %Y", tz = "GMT")повернуті значення. (Я не маю на увазі, що month.abbвикористовується для відповідності% B, оскільки в документах сказано, що відповідність залежить від локалі.)
IRTFM

6
@CarlWitthoft Деякі з нас час від часу спотикаються. Дякую за удар, поки я не буду. У цьому питанні я зрозумів досить багато речей: я включив sessionInfo (), я шукав, розповів, що я шукав, і включив посилання, і я тримав це як можна ретельніше. Я пропустив один рядок у? As.Date, і ви надаєте мені лікування 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).

Якщо ви отримуєте цю помилку, рішення полягає у визначенні формату, в якому перебувають ваша дата (або дати), використовуючи формати, описані в ?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" суперечить повідомленню про помилку.
Джошуа Ульріх

31

Іншими словами, чи є краще рішення, ніж необхідність вказувати формат?

Так, в даний час (тобто в кінця 2016), завдяки 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

Просто використовував будь-який пакет, і він працював чудово, за винятком багатьох НС. Після того, як я провів trimws () на векторі дати, все було ідеально.
lawyeR

Я теж використовую метричну тонну!
Dirk Eddelbuettel

Виглядає так просто! Я використовував anydate () у стовпці із рядковими значеннями мм-дд (без рр). Усі значення <chr> у стовпці успішно перетворені в <дата>. На жаль, він встановив рік «1400» замість «2020». ¯_ (ツ) _ / ¯
сова

Ну, не зовсім. Як я відповів у кількох інших запитаннях на цьому сайті, mm-ddце не дата (ані мм-рр, ані мм-рррр). Ви не можете проаналізувати те, чого там немає.
Дірк Еддельбюттель

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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.