Почему операторы R if ifsese не возвращают векторы?
Я обнаружил, что R’s ifelse заявления очень удобны время от времени. Например:
ifelse(TRUE,1,2) # [1] 1 ifelse(FALSE,1,2) # [1] 2
Но меня несколько смущает следующее поведение.
ifelse(TRUE,c(1,2),c(3,4)) # [1] 1 ifelse(FALSE,c(1,2),c(3,4)) # [1] 3
тоifelse(TRUE,c(1,2),c(3,4)) # [1] 1 ifelse(FALSE,c(1,2),c(3,4)) # [1] 3
Это выбор дизайна, который выше моего платного?
- Преобразование эпохи UNIX в объект Date
- Переименовать несколько столбцов по именам
- Удалить обратную косую черту с символьной строки
- Каковы различия между «=» и «<-» в R?
- Замена NA с последним значением, отличным от NA
- Количество строк в каждой группе
- Выбор строк из фрейма данных на основе значений в векторе
- Какая самая большая R-gotcha, с которой вы столкнулись?
- Ошибка: неожиданный символ / ввод / строка константа / числовая константа / SPECIAL в моем коде
- Как отлаживать «контрасты могут быть применены только к факторам с 2 или более уровнями»?
- Объедините два кадра данных по строкам (rbind), когда они имеют разные наборы столбцов
- Уровни фактора падения в подмножестве данных
- Как объединить (объединить) кадры данных (внутренний, внешний, левый, правый)?
Документация для ifelse
гласит:
ifelse
возвращает значение с той же формой, что иtest
который заполняется элементами, выбранными изyes
илиno
зависимости от того, является ли элементtest
TRUE
илиFALSE
.
Поскольку вы проходите тестовые значения длины 1, вы получаете результаты по длине 1. Если вы пройдете более длинные тестовые векторы, вы получите более длительные результаты:
> ifelse(c(TRUE, FALSE), c(1, 2), c(3, 4)) [1] 1 4
Поэтому ifelse
предназначен для конкретной цели тестирования вектора логических чисел и возврата вектора той же длины, заполненного элементами, взятыми из (вектора) yes
и no
аргументов.
Это обычная путаница из-за имени функции, чтобы использовать это, когда на самом деле вы хотите просто создать нормальную if () {} else {}
.
Уверен, вам нужна простая инструкция if
вместо ifelse
– в R, if
это не просто структура streamа управления, она может вернуть значение:
> if(TRUE) c(1,2) else c(3,4) [1] 1 2 > if(FALSE) c(1,2) else c(3,4) [1] 3 4
да, я думаю, что ifelse () действительно предназначен для тех случаев, когда у вас большой длинный вектор тестов и вы хотите сопоставить каждый из двух вариантов. Например, я часто делаю цвета для plot () следующим образом:
plot(x,y, col = ifelse(x>2, 'red', 'blue'))
Если бы у вас был большой длинный вектор тестов, но были нужны пары для выходов, вы могли бы использовать sapply()
или plyr
llply()
или что-то еще, возможно.
Обратите внимание, что вы можете обойти проблему, если назначить результат внутри ifelse
:
ifelse(TRUE, a <- c(1,2), a <- c(3,4)) a # [1] 1 2 ifelse(FALSE, a <- c(1,2), a <- c(3,4)) a # [1] 3 4
Иногда пользователю просто требуется инструкция switch
вместо ifelse
. В таком случае:
condition <- TRUE switch(2-condition, c(1, 2), c(3, 4)) #### [1] 1 2
(что является еще одним вариантом синтаксиса ответа Кена Уильямса)
Вот такой подход, подобный предложенному Кэтом, но он может работать с существующими заранее назначенными векторами
Он основан на использовании get()
следующим образом:
a <- c(1,2) b <- c(3,4) get(ifelse(TRUE, "a", "b")) # [1] 1 2