Почему операторы ifelse R не могут возвращать векторы?
-
20-09-2019 - |
Вопрос
Я обнаружил, что заявления 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
Это выбор дизайна, который выше моего уровня оплаты?
Решение
Документация для ifelse
состояния:
ifelse
возвращает значение с той же формой , что иtest
который заполнен элементами, выбранными из любогоyes
илиno
в зависимости от того, является ли элемент изtest
являетсяTRUE
илиFALSE
.
Поскольку вы передаете тестовые значения длины 1, вы получаете результаты длины 1.Если вы передадите более длинные тестовые векторы, вы получите более длинные результаты:
> ifelse(c(TRUE, FALSE), c(1, 2), c(3, 4))
[1] 1 4
Итак ifelse
предназначен для конкретной цели тестирования вектора логических значений и возврата вектора той же длины, заполненного элементами, взятыми из (vector) yes
и no
аргументы.
Это распространенная путаница из-за названия функции - использовать это, когда на самом деле вам нужен просто обычный if () {} else {}
строительство вместо этого.
Другие советы
Бьюсь об заклад, вы хотите простого 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
:
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
да, я думаю, ifelse() действительно предназначен для случаев, когда у вас большой длинный вектор тестов и вы хотите сопоставить каждый из них с одним из двух вариантов.Например, я часто делаю цвета для plot() таким образом:
plot(x,y, col = ifelse(x>2, 'red', 'blue'))
Если у вас был большой длинный вектор тестов, но вам нужны были пары для выходных данных, вы могли бы использовать sapply()
или plyr
's llply()
или что-то в этомроде, возможно.
Вот подход, аналогичный тому, что предложен Cath, но он может работать с существующими предварительно назначенными векторами
Она основана на использовании get()
вот так:
a <- c(1,2)
b <- c(3,4)
get(ifelse(TRUE, "a", "b"))
# [1] 1 2
Иногда пользователю просто нужно switch
утверждение вместо ifelse
.В таком случае:
condition <- TRUE
switch(2-condition, c(1, 2), c(3, 4))
#### [1] 1 2
(это еще один синтаксический вариант ответа Кена Уильямса)
используйте `если`, например
> `if`(T,1:3,2:4)
[1] 1 2 3
В вашем случае, используя if_else
От dplyr
это было бы полезно: if_else
является более строгим, чем ifelse
, и выдает ошибку для вашего случая:
library(dplyr)
if_else(TRUE,c(1,2),c(3,4))
#> `true` must be length 1 (length of `condition`), not 2