Формат символов не может измениться на формат даты

У меня есть данные и есть столбец с именем Date, я ввожу данные в R.
Вот мои данные:

unique(data$Date)
 [1] ""           "2016/12/20" "2016/12/27" "2017/1/7"   "2017/1/27"  "2017/2/1"   "2017/2/2"   "2017/2/5"   "2017/2/6"   "2017/2/7"  
[11] "2017/2/8"   "2017/2/10"  "2017/2/11"  "2017/2/13"  "2017/2/14"  "2017/2/15"  "2017/2/17"  "2017/2/16"  "2017/2/24"  "2017/2/19" 
[21] "2017/2/21"  "2017/2/20"  "2017/2/26"  "2017/2/22"  "2017/3/2"   "2017/2/25"  "2017/2/28"  "2017/3/1"   "2017/3/4"   "2017/3/5"  
[31] "2017/3/6"   "2017/3/10"  "2017/3/8"   "2017/3/9"   "2017/3/11"  "2017/3/12"  "2017/3/13"  "2017/3/15"  "2017/3/29"  "2017/5/13" 
[41] "2015/10/5"  "2016/2/22"  "2015/3/6"   "2015/3/7"   "2015/10/15" "2015/3/9"   "2016/1/30"  "2015/10/29" "2015/10/24" "2015/10/17"
[51] "2016/1/8"   "2015/9/24"  "2016/2/15"  "2015/12/8"  "2015/12/10" "2016/2/6"   "2015/11/29" "2016/1/23"  "2015/10/11" "2016/2/16" 
[61] "2015/9/28"  "2016/1/29"  "2015/11/27" "2015/10/12" "2015/11/1"  "2015/11/16" "2015/10/10" "2015/11/30" "2016/1/2"   "2016/1/21" 
[71] "2016/4/22"  "2015/10/21" "2015/11/12" "2015/12/28" "2015/12/30" "2015/11/6"  "2015/10/8"  "2015/12/6"  "2016/1/24"  "2016/1/17" 
[81] "2016/2/26"  "2016/3/6"   "2016/2/17"  "2016/1/11"  "2015/12/3"  "2016/2/11"  "2015/11/22" "2015/10/2"  "2015/10/3"  "2015/11/4" 
[91] "2016/2/10"  "2015/12/9"  "2015/10/9"  "2015/12/1"  "2016/2/25"  "2016/1/19"  "2016/1/18"  "2015/12/13" "2016/2/14"  "2016/3/10" 

class(data$Date)
[1] "character"

Я меняю этот формат character на date с помощью as.Date():

data$Date <- as.Date(data$Date)
Error in charToDate(x) : 
character string is not in a standard unambiguous format

Я не знаю, как понять. Думаю проблема "" в данных. У меня также есть другой столбец с именем Date2, но в этом столбце нет "".
Есть предложения?

Кроме того, если я хочу сделать as.Date с двумя столбцами одновременно и определить указанный формат, например `as.Date(x, "%Y/%m/%d"), как мне это сделать?

data[,c("Date", "Date2") := lapply(.SD, as.Date), .SDcols = c("Date", "Date2")]

person Peter Chen    schedule 21.07.2017    source источник
comment
Укажите формат даты. as.Date(x, "%Y/%m/%d")   -  person Ronak Shah    schedule 21.07.2017
comment
@RonakShah - я думаю, он должен автоматически распознавать этот формат   -  person SymbolixAU    schedule 21.07.2017
comment
@SymbolixAU В идеале так и должно быть, потому что as.Date("2017/01/01") возвращает правильную дату. Может быть, важна точность цифр?   -  person Ronak Shah    schedule 21.07.2017
comment
@RonakShah Спасибо. оно работает. Однако я не знаю, зачем нужно добавлять "%Y/%m/%d".   -  person Peter Chen    schedule 21.07.2017
comment
Это связано с первым случаем "" — сравните as.Date(c("","2015/10/5")) и as.Date(c("2015/10/5")). К сожалению, R не умеет читать мысли (пока).   -  person thelatemail    schedule 21.07.2017
comment
Ага. Я понял. Это работает даже для as.Date("2017/1/1") без format, но это потому, что у вас есть одно пустое значение в начале, поэтому важно упомянуть формат.   -  person Ronak Shah    schedule 21.07.2017
comment
Может быть, я могу сначала изменить "" на NA, а затем изменить формат на date? Это возможно?   -  person Peter Chen    schedule 21.07.2017
comment
Итак, as.Date проверяет первый элемент, чтобы «угадать» формат, а затем применяет его к каждому последующему? Потому что as.Date(c("2015/10/5", "")) в порядке. Но если первый — "", то у него проблемы?   -  person SymbolixAU    schedule 21.07.2017
comment
@SymbolixAU - вы можете увидеть эту проверку, если наберете as.Date.character в консоли и проверите код. Кажется, он делает то, о чем вы догадываетесь.   -  person thelatemail    schedule 21.07.2017
comment
Для обновленного вопроса следует использовать data[, :=(Date = as.Date(Date), Date2 = as.Date(Date2))] (с обратными галочками вокруг :=)   -  person SymbolixAU    schedule 21.07.2017
comment
@SymbolixAU да, это работает. Однако мой код не может работать. Я не знаю почему.   -  person Peter Chen    schedule 21.07.2017
comment
Вы указали формат "%Y/%m/%d"?   -  person SymbolixAU    schedule 21.07.2017


Ответы (2)


Как указано в комментариях, ответ заключается в том, что вам нужно указать формат даты, которую вы конвертируете. Что в вашем случае "%Y/%m/%d"

data$Date <- as.Date(data$Date, "%Y/%m/%d")

Объяснение

Причина, по которой вам нужно это сделать, заключается в том, что первая запись в вашем векторе — "", И вы не указали формат.

Функция as.Date при применении к персонажу сначала проверяет, отсутствует ли аргумент format. Если это так, он пытается угадать формат на основе первого элемента вектора.

Он проверяет форматы "%Y-%m-%d" и "%Y/%m/%d", выполняя

xx <- ""
strptime(xx, "%Y-%m-%d")
NA
strptime(xx, "%Y/%m/%d")
NA

В частности, он использует следующий тест (где xx — первый элемент вашего вектора)

if(is.na(xx) || 
    !is.na(strptime(xx, f <- "%Y-%m-%d", tz = "GMT")) || 
    !is.na(strptime(xx, f <- "%Y/%m/%d", tz = "GMT"))){
  print("success!")     ## I added this print statement for illustration purposes
}else{
  stop("character string is not in a standard unambiguous format")
}

Итак, как видите, xx оценивается как FALSE во всех условиях if, поэтому функция должна ввести метод stop.

Чтобы продемонстрировать, см. результаты этих утверждений

as.Date(c("2015/10/5", ""))  
# [1] "2015-10-05" NA
## SUCCESS, because it can 'guess' the first entry's format

as.Date(c("", "2015/10/5"))  
## ERROR: can't 'guess' the first entry's format

as.Date(c("2015/10/5", ""), format = "%Y/%m/%d") 
# [1] "2015-10-05" NA
## SUCCESS, because you've specified the format

as.Date(c("2015-10/5", "")) 
## ERROR: you haven't specified the format, 
## AND it's not one of the 'guessed' options ("%Y-%m-%d", "%Y/%m/%d")
person SymbolixAU    schedule 21.07.2017

Вы можете использовать функцию ymd() в пакете lubridate для преобразования дат, и пустые строки будут преобразованы в NA. Например,

> library(lubridate)
> (newdates <- ymd(dates))
   [1] NA           "2016-12-20" "2016-12-27" "2017-01-07" "2017-01-27" "2017-02-01" "2017-02-02" "2017-02-05"
   [9] "2017-02-06" "2017-02-07" "2017-02-08" "2017-02-10" "2017-02-11" "2017-02-13" "2017-02-14" "2017-02-15"
   [17] "2017-02-17" "2017-02-16" "2017-02-24" "2017-02-19" "2017-02-21" "2017-02-20" "2017-02-26" "2017-02-22"
   [25] "2017-03-02" "2017-02-25" "2017-02-28" "2017-03-01" "2017-03-04" "2017-03-05" "2017-03-06" "2017-03-10"
   [33] "2017-03-08" "2017-03-09" "2017-03-11" "2017-03-12" "2017-03-13" "2017-03-15" "2017-03-29" "2017-05-13"
   [41] "2015-10-05" "2016-02-22" "2015-03-06" "2015-03-07" "2015-10-15" "2015-03-09" "2016-01-30" "2015-10-29"
   [49] "2015-10-24" "2015-10-17" "2016-01-08" "2015-09-24" "2016-02-15" "2015-12-08" "2015-12-10" "2016-02-06"
   [57] "2015-11-29" "2016-01-23" "2015-10-11" "2016-02-16" "2015-09-28" "2016-01-29" "2015-11-27" "2015-10-12"
   [65] "2015-11-01" "2015-11-16" "2015-10-10" "2015-11-30" "2016-01-02" "2016-01-21" "2016-04-22" "2015-10-21"
   [73] "2015-11-12" "2015-12-28" "2015-12-30" "2015-11-06" "2015-10-08" "2015-12-06" "2016-01-24" "2016-01-17"
   [81] "2016-02-26" "2016-03-06" "2016-02-17" "2016-01-11" "2015-12-03" "2016-02-11" "2015-11-22" "2015-10-02"
   [89] "2015-10-03" "2015-11-04" "2016-02-10" "2015-12-09" "2015-10-09" "2015-12-01" "2016-02-25" "2016-01-19"
   [97] "2016-01-18" "2015-12-13" "2016-02-14" "2016-03-10"
> is.Date(newdates)
 [1] TRUE    
person jdb    schedule 21.07.2017