Каковы стандартные однозначные форматы даты для преобразования строки в дату в R?

Пожалуйста, примите во внимание следующее

$ 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

person Matt Dowle    schedule 07.02.2013    source источник
comment
судя по определению функции as.Date.character, ввод проверяется только для этих двух форматов: "%Y-%m-%d" и "%Y/%m/%d". Если он может совпадать с одним из них, это будет считаться однозначным.   -  person plannapus    schedule 07.02.2013
comment
@CarlWitthoft Я даже читал, кажется, подразумевается, что ответ ослепляюще очевиден в ?as.Date. Где это помогает?   -  person Matt Dowle    schedule 07.02.2013
comment
@plannapus Спасибо, похоже, это ответ. Не могли бы вы добавить это, тогда я могу согласиться.   -  person Matt Dowle    schedule 07.02.2013
comment
Возможно, 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, поскольку в документации указано, что сопоставление зависит от локали.)   -  person IRTFM    schedule 07.02.2013
comment
@CarlWitthoft Некоторые из нас то и дело спотыкаются. Спасибо за удар, пока я внизу. В этом вопросе я понял несколько вещей: я включил sessionInfo (), я искал, сказал вам, что я искал, и включил ссылку, я сохранил ее как можно более лаконично. Я пропустил одну строчку в? As.Date, а вы меня лечите TFM. Мы не можем все время быть такими же идеальными, как вы.   -  person Matt Dowle    schedule 07.02.2013
comment
@MatthewDowle, извини, если я сильно упал. Я думаю, что вспыльчивость началась, когда вы, казалось, перепутали однозначное для достаточно хорошо образованного человека с однозначным для бедного и беспомощного фрагмента кода. :-(   -  person Carl Witthoft    schedule 07.02.2013


Ответы (6)


Это задокументированное поведение. От 1_:

формат: строка символов. Если не указано иное, он попробует «% 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; см. Также strptime, as.POSIXct и as.Date неожиданно возвращают NA).

person Joshua Ulrich    schedule 07.02.2013
comment
@BenBolker Как насчет "character string is not either %Y-%m-%d or %Y/%m/%d"? - person Matt Dowle; 07.02.2013
comment
Такое поведение определенно задокументировано в ?as.Date (+1). Однако стандартный однозначный формат сообщения об ошибке по иронии судьбы неоднозначен, о чем свидетельствуют 23 предыдущих вопроса. Более прямое сообщение об ошибке, например, формат не распознан, см. Документацию, может улучшить взаимодействие с пользователем. Кроме того, я не верю, что 01.01.2000 соответствует ISO-8601 (2000-01-01 - ISO-8601), что добавляет двусмысленности. - person jthetzel; 07.02.2013
comment
@jthetzel: вы правы, 01.01.2000 - это не ISO-8601. Я имел в виду, что лично я считаю ISO-8601 стандартным однозначным форматом. И я согласен с тем, что as.Date отсутствие жалоб на 01.01.2000 несовместимо с сообщением об ошибке. - person Joshua Ulrich; 03.08.2015

Другими словами, есть ли лучшее решение, чем необходимость указывать формат?

Да, есть сейчас (т.е. в конце 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() они это делают. Без формата.

person Dirk Eddelbuettel    schedule 20.11.2016
comment
Мы пришли сюда только потому, что у нас возник еще один вопрос о том, что что-то пытается проанализировать даты с неполным форматом. Для полных у нас теперь есть кое-что. Меня это вполне устраивает - это был назойливый вопрос. И, разумеется, anytime() одинаково полезен для POSIXct. - person Dirk Eddelbuettel; 21.11.2016
comment
Просто использовал пакет Anytime, и он отлично работал, за исключением нескольких НА. После того, как я запустил trimws () для вектора даты, все стало идеально. - person lawyeR; 07.12.2017
comment
Я тоже использую метрическую тонну! - person Dirk Eddelbuettel; 07.12.2017
comment
Выглядит так просто! Я использовал anydate () для столбца со строковыми значениями mm-dd (без yy). Все значения ‹chr› в столбце были успешно преобразованы в ‹date›. К сожалению, он установил год «1400» вместо «2020». ¯_ (ツ) _ / ¯ - person owlstone; 23.05.2020
comment
Не совсем так. Как я ответил на несколько других вопросов на этом сайте, mm-dd не является датой (ни мм-гг, ни мм-гггг). Вы не можете разобрать то, чего там нет. - person Dirk Eddelbuettel; 23.05.2020

В дополнение к ответу @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, это считается неоднозначным, а если и не однозначным.

person plannapus    schedule 07.02.2013

Преобразование даты без указания текущего формата может легко вызвать эту ошибку.

Вот пример:

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.
person HassanSh__3571619    schedule 19.12.2015

У меня это отлично работает, независимо от того, как дата была закодирована ранее.

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

Например, если дата: 01 января 2000 г., я рекомендую использовать

library(lubridate)
date_corrected<-dmy("01 Jan 2000")
date_corrected
[1] "2000-01-01"
class(date_corrected)
[1] "Date"

lubridate имеет функцию почти для всех типов свиданий.

person Cindy Carolina Lugo Rozo    schedule 12.07.2021