Я использую функцию ifelse()
для манипулирования вектором даты. Я ожидал, что результат будет классным Date
, и был удивлен, numeric
получив вместо этого вектор. Вот пример:
dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'))
dates <- ifelse(dates == '2011-01-01', dates - 1, dates)
str(dates)
Это особенно удивительно, потому что выполнение операции по всему вектору возвращает Date
объект.
dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04','2011-01-05'))
dates <- dates - 1
str(dates)
Должен ли я использовать какую-то другую функцию для работы с Date
векторами? Если да, то какая функция? Если нет, как мне заставить ifelse
вернуть вектор того же типа, что и вход?
Страница справки для ifelse
указывает, что это функция, а не ошибка, но я все еще пытаюсь найти объяснение тому, что я считаю удивительным поведением.
r
datetime
if-statement
Zach
источник
источник
if_else()
в пакете dplyr есть функция, которая может заменитьifelse
при сохранении правильных классов объектов Date - она опубликована ниже как недавний ответ. Я обращаю внимание на это здесь, поскольку оно решает эту проблему, предоставляя функцию, которая тестируется модулем и документируется в пакете CRAN, в отличие от многих других ответов, которые (по состоянию на этот комментарий) были ранжированы впереди нее.Ответы:
Вы можете использовать
data.table::fifelse
(data.table >= 1.12.3
) илиdplyr::if_else
.data.table::fifelse
dplyr::if_else
Из
dplyr 0.5.0
заметок о выпуске :источник
true
's иfalse
' уровней.if_else
быть NA? Я попробовал логическиеNA_
варианты, и ничто не мешает, и я не верю, что естьNA_double_
NA
вas.Date
.NA_real_
, @roarkz. и @Henrik, ваш комментарий решил мою проблему.Это относится к документированной стоимости из
ifelse
:Сводится к его последствиям,
ifelse
заставляет факторы терять свои уровни, а даты теряют свой класс, и восстанавливается только их режим («числовой»). Попробуйте это вместо:Вы можете создать
safe.ifelse
:Более позднее примечание: я вижу, что Хэдли встроил
if_else
в пакет magrittr / dplyr / tidyr пакетов для формирования данных.источник
safe.ifelse <- function(cond, yes, no) structure(ifelse(cond, yes, no), class = class(yes))
ifelse()
не является "безопасной" .Объяснение DWin точно на месте. Я некоторое время возился и боролся с этим, прежде чем понял, что могу просто заставить класс после заявления ifelse:
Сначала это показалось мне немного «хакерским». Но теперь я просто считаю, что это небольшая цена за отдачу от производительности, которую я получаю от ifelse (). Плюс это все еще намного более кратко чем петля.
источник
for
оператор присваивает значение элементов вVECTOR
кNAME
, но не их классу .Предлагаемый метод не работает со столбцами факторов. Я хотел бы предложить это улучшение:
Между прочим: ifelse отстой ... с большой силой приходит большая ответственность, то есть преобразование типов матриц 1x1 и / или чисел [когда они должны быть добавлены, например] нормально для меня, но это преобразование типов в ifelse явно нежелательно. Я столкнулся с той же самой «ошибкой» ifelse несколько раз, и она просто продолжает красть мое время :-(
FW
источник
yes
иno
и что вы бы сначала проверить, что они оба фактора. Вам, вероятно, потребуется преобразовать в символ, а затем заново сопоставить с «объединенными» уровнями.Причина, по которой это не сработает, заключается в том, что функция ifelse () преобразует значения в факторы. Хороший обходной путь - преобразовать его в символы перед его оценкой.
Это не потребует никакой библиотеки, кроме базы R.
источник
Ответ, предоставленный @ fabian-werner, великолепен, но объекты могут иметь несколько классов, и «factor» может не обязательно быть первым, возвращаемым
class(yes)
, поэтому я предлагаю эту небольшую модификацию, чтобы проверить все атрибуты класса:Я также отправил запрос команде разработчиков R на добавление документированной опции, чтобы base :: ifelse () сохраняла атрибуты на основе выбора пользователем того, какие атрибуты сохранять. Запрос здесь: https://bugs.r-project.org/bugzilla/show_bug.cgi?id=16609 - он уже был помечен как «WONTFIX» на том основании, что он всегда был таким, как сейчас, но я привел дополнительный аргумент о том, почему простое добавление может избавить от головной боли пользователей R. Возможно, ваше «+1» в этой ветке ошибок побудит команду R Core взглянуть еще раз.
РЕДАКТИРОВАТЬ: Вот лучшая версия, которая позволяет пользователю указать, какие атрибуты сохранять, либо «cond» (поведение по умолчанию ifelse ()), «да», поведение в соответствии с приведенным выше кодом, либо «нет», для случаев, когда атрибуты значения "нет" лучше:
источник
inherits(y, "factor")
может быть "более правильным", чем"factor" %in% class.y
inherits
может быть лучше.