Почему операторы R ifelse не могут возвращать векторы?


я обнаружил, что операторы ifelse R время от времени довольно удобны. Например:

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

это выбор дизайна, который выше моей зарплаты?

6 85

6 ответов:

документация 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 заявление вместо ifelse - в R,if - это не просто структура потока управления, она может возвращать значение:

> 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 ' s 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

(что является еще одним синтаксическим вариантом ответа Кена Уильямса)

вот подход, аналогичный предложенному Cath, но он может работать с существующими предварительно назначенными векторами

С помощью get() вот так:

a <- c(1,2)
b <- c(3,4)
get(ifelse(TRUE, "a", "b"))
# [1] 1 2