Как использовать as.Date, если в одном столбце есть NA, пустые ячейки и разные форматы?

Внутри моего фрейма данных столбец состоит из двух типов форматов даты (%Y-%m-%d и %d/%m/%Y), пустых ячеек и NA. Следующий метод - моя попытка, которая не дала желаемого результата. Я попытался преобразовать их следующим образом....

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

Затем соедините их вместе...

a[is.na(a)] <- b[!is.na(b)] 

Однако я получаю сообщение об ошибке, говорящее о другом количестве строк. Я доверяю этому из-за наличия пустых ячеек и NA. Есть ли способ, где я могу сложить a + b в соответствии с их номером строки/наблюдением/рейтингом?

Заранее спасибо за ответ.


person Teddy    schedule 12.02.2018    source источник
comment
Добро пожаловать в StackOverflow! Прочтите информацию о том, как задать хороший вопрос и как поставить воспроизводимый пример. Это значительно облегчит другим людям помощь.   -  person Sotos    schedule 12.02.2018
comment
Проверьте в любое время pckg   -  person David Arenburg    schedule 12.02.2018
comment
Во что вы хотите перевести пустые ячейки ('') и NA? Также, пожалуйста, добавьте воспроизводимые данные (используйте dput())   -  person smci    schedule 12.02.2018
comment
Спасибо за комментарий, ребята. @smci У меня нет предпочтений, пока NA и пустые ячейки не влияют на то, как я манипулирую данными. Что бы вы сделали, если бы столкнулись с той же проблемой? Я попытался изменить его на 0000, но понял, что они меняются обратно на NA, когда я применяю as.Date к данным.   -  person Teddy    schedule 13.02.2018
comment
Что ж, старый и проверенный способ изменения пустых дат или дат NA, чтобы они обрабатывались как дата и не приводили к выводу переменной длины, состоял бы в том, чтобы изменить их на какое-то контрольное значение, которое явно бессмысленно, например. 9/9/9999. Но все же, пожалуйста, добавьте, скажем, 10 примеров записей воспроизводимых данных.   -  person smci    schedule 13.02.2018
comment
Сойдет, пожалуйста, дайте мне немного времени, чтобы понять, как поделиться воспроизводимыми данными, так как я все еще пытаюсь понять код @kgolyaev ниже. Уже провел утро, пытаясь разбить его и понять, но мне это кажется сложным. Я отношусь к этому серьезно, так как я действительно хочу понять это плохо. Спасибо за терпение.   -  person Teddy    schedule 13.02.2018


Ответы (1)


Я думаю, что вам нужно ifelse:

x = c("2012-01-01", "13/01/2012", "")
x1 = as.Date(x, format="%Y-%m-%d")
x2 = as.Date(x, format="%d/%m/%Y")
y = as.Date(
  ifelse(!is.na(x1), as.Date(x1), 
         ifelse(!is.na(x2), x2, x1)), 
  origin = as.Date("1970/01/01")
)
y
[1] "2012-01-01" "2012-01-13" NA   

По какой-то причине мне пришлось завернуть ifelse в as.Date(), иначе даты печатались как числа, а не как фактические даты. В этом случае необходим аргумент origin.

Изменить

Вот как работает приведенный выше код. ifelse(condition, value_if_true, value_if_false) — это векторизованная функция, которая принимает в качестве аргументов три вектора одинаковой длины. (Способ работы R, если один из этих аргументов является единственным значением, он будет автоматически повторяться нужное количество раз, термин для этого — «трансляция».) Выполнение ifelse() выглядит следующим образом:

а) Для каждого элемента в condition проверьте, является ли он TRUE или FALSE.

б) Если condition равно TRUE, взять соответствующее значение из вектора value_if_true.

c) В противном случае, если condition равно FALSE, взять соответствующее значение из вектора value_if_false

Теперь вы можете вкладывать ifelse() друг в друга, что позволяет выполнять трехэтапную проверку условий или даже больше, если это необходимо. Имейте в виду, что вложение нескольких вызовов ifelse может очень быстро привести к беспорядку.

С этим знанием приведенный выше код должен быть простым для разбора:

1) x создает пример вектора дат, хранящихся в виде строк с разными форматами.

2) x1 правильно анализирует первую дату и не может анализировать вторую дату.

3) x2 правильно разбирает второй формат даты, но не может разобрать первую дату.

4) Затем два вложенных вызова ifelse объединяют правильно проанализированные даты в один вектор. Сначала ifelse проверяет правильность анализа первого формата даты (!is.na(x) означает "всякий раз, когда значение x не равно NA") и возвращает непропущенные значения из x1. Если x1 отсутствует, он вызывает второй ifelse, который возвращает неотсутствующие значения из x2, а затем, если x2 также отсутствует, он возвращает пропущенные значения в окончательный результат.

5) По какой-то причине вложенные вызовы ifelse возвращают даты, отформатированные как числа, а не как строки, поэтому я оборачиваю результат 4) в as.Date, чтобы получить красиво отформатированные даты. В R, когда вы пытаетесь преобразовать числа в даты, вы должны указать origin — даты интерпретируются как количество дней, прошедших с некоторой заранее определенной даты начала, которая в R — 1 января 1970 года.

Надеюсь это поможет.

person kgolyaev    schedule 12.02.2018
comment
Ваш метод сработал, хотя я не понимаю причин, лежащих в его основе, поскольку я все еще относительно новичок в R и не разобрался с большинством концепций, но большое спасибо! Если у вас есть время, не могли бы вы объяснить здесь использование ifelse? Заранее спасибо. - person Teddy; 13.02.2018
comment
Немного отредактировал ответ, чтобы лучше объяснить. - person kgolyaev; 13.02.2018
comment
Ценю ваше время и усилия, чтобы объяснить это мне. Вы хороший человек! Большое спасибо! - person Teddy; 20.02.2018