R의 ifelse 문이 벡터를 반환 할 수없는 이유는 무엇입니까?


118

R의 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

이것은 내 급여보다 높은 디자인 선택입니까?


1
ifelse에 대한 약간의 이상한 디자인은 다른 것이 작동하면 간단하다는 사실을 감안할 때.
2sb

4
ifelse는 벡터화 된 함수입니다. 다른 작업에 사용해야합니다.
marbel

답변:


99

ifelse상태에 대한 문서 :

ifelse의 요소 가 또는 인지에 따라 또는 test에서 선택한 요소로 채워진 동일한 모양의 값을 반환합니다 .yesnotestTRUEFALSE

길이 1의 테스트 값을 통과하므로 길이 1의 결과를 얻게됩니다. 더 긴 테스트 벡터를 통과하면 더 긴 결과를 얻을 수 있습니다.

> ifelse(c(TRUE, FALSE), c(1, 2), c(3, 4))
[1] 1 4

따라서 ifelse부울 벡터를 테스트하고 (벡터) yesno인수 에서 가져온 요소로 채워진 동일한 길이의 벡터를 반환하는 특정 목적을위한 것입니다 .

함수의 이름으로 인해 실제로 정상적인 if () {} else {}구성 을 원할 때 이것을 사용하는 것은 일반적인 혼란 입니다.


16
아마도 두 번째 문장 세트에 대해 정말로 원했던 것은 if (TRUE) c(1,2) else c(3,4).
Jonathan Chang

69

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

@Ken, 이것은 나를 위해 작동합니다. " Warning in if (req(inputval) == "All") { : the condition has length > 1 and only the first element will be used"이 경고를 제거하려면 어떻게해야합니까?
user5249203

1
@ user5249203, 질문 및 Ken의 대답은 조건이 단일 값, 즉 길이 1의 벡터 인 경우를 나타냅니다. 경고 req(inputval)는 더 많은 요소가 있음을 나타냅니다 . 단일 값을 얻으려면 함수 any()또는 all()유용 할 수 있습니다.
Uwe

12

내부에 결과를 할당하면 문제를 피할 수 있습니다 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

3
IMHO, 이것은 할당 ifelse()을위한 제어 흐름 대신 벡터화 된 함수 를 오용하는 것을 장려 if ... else ...합니다. 조건이 하나 인 경우 TRUE또는 FALSE값을, 나는 쓰는 것을 선호 a <- if (TRUE) c(1,2) else c(3,4)또는if (TRUE) a <- c(1,2) else a <- c(3,4)
우베

1
@Uwe ifelse대신 사용할 때 성능 차이가 없다고 생각하지만 if... else단일 조건의 경우 실제로 문제 ifelse가 될 수 있으며 일부 경우 코드 내부에서 선호 될 수 있습니다 (여기에서 간단한 추측), 동의하지 않을 수 있습니다 ;-). 나는 단지 ifelse.
Cath

9

네, ifelse ()는 정말 긴 테스트 벡터를 가지고 있고 각각 두 가지 옵션 중 하나에 매핑하고 싶을 때를 위해 설계되었다고 생각합니다. 예를 들어, 저는 종종 다음과 같은 방식으로 plot ()에 대해 색상을 지정합니다.

plot(x,y, col = ifelse(x>2,  'red', 'blue'))

긴 테스트 벡터가 있지만 출력을 위해 쌍을 원했다면 sapply()또는 plyr's llply()또는 무언가를 사용할 수 있습니다 .


4

때때로 사용자 switchifelse. 이 경우 :

condition <- TRUE
switch(2-condition, c(1, 2), c(3, 4))
#### [1] 1 2

(Ken Williams의 답변의 또 다른 구문 옵션입니다)


4

다음은 Cath가 제안한 것과 유사한 접근 방식이지만 기존에 미리 할당 된 벡터와 함께 사용할 수 있습니다.

다음 get()과 같이 사용하는 것을 기반으로합니다 .

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

4

'if'사용, 예 :

> `if`(T,1:3,2:4)
[1] 1 2 3

이것은 ifelse의 예상 기능을 실제로 제공 할 수있는 유일한 답변입니다.
sus_mlm

2

귀하의 경우 if_elsefrom 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

0

everydropr 에서 발견 :

ifelse(rep(TRUE, length(c(1,2))), c(1,2),c(3,4))
#>[1] 1 2

조건의 결과를 복제하여 원하는 길이를 반환 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.