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の少し奇妙なデザインは、他のifが機能するという単純な事実を考慮しています。
2sb

4
ifelseはベクトル化された関数です。さまざまなタスクに使用する必要があります。
marbel 2014年

回答:


99

ifelse状態のドキュメント:

ifelse同じ形状の戻り値testのいずれかから選択される元素で満たされているyesか、 noの要素かどうかに応じtestていますTRUEか、FALSE

長さ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)
ジョナサンチャン

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

@ケン、これは私にとってはうまくいきますが、一定の警告が必要な" Warning in if (req(inputval) == "All") { : the condition has length > 1 and only the first element will be used"ものが表示されても、この警告を取り除くにはどうすればよいですか?
user5249203 2018年

1
@ user5249203では、質問とケンの答えは、条件が単一の値、つまり長さ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
私見、これは、割り当ての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)
Uwe

1
@Uwe私は...のifelse代わりに使用した場合のパフォーマンスの違いを考えていませんif... else単一の条件の場合は実際に問題になるifelse可能性があり、場合によってはコード内で優先される可能性があります(ここで簡単に推測してください)。 ;-)。で道を示したかっただけifelseです。
Cath

9

ええ、ifelse()は、テストの大きな長いベクトルがあり、それぞれを2つのオプションのいずれかにマップしたい場合のために本当に設計されていると思います。たとえば、私はしばしばplot()の色を次のようにしています:

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

あなたがテストの大きな長いベクトルを持っていたが、出力用のペアを望んでいた場合は、使用できるsapply()plyrllply()、おそらく、または何かを。


4

場合によっては、ユーザーがのswitch代わりにステートメントを必要とすることがありますifelse。その場合:

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

(これはケン・ウィリアムズの答えの別の構文オプションです)


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.