switch()ステートメントの使用法


106

Rのswitchステートメントについて少し混乱しています。単に関数をググるだけで、次のような例が得られます。

スイッチの一般的な用途は、関数への引数の1つの文字値に従って分岐することです。

 > centre <- function(x, type) {
 + switch(type,
 +        mean = mean(x),
 +        median = median(x),
 +        trimmed = mean(x, trim = .1))
 + }
 > x <- rcauchy(10)
 > centre(x, "mean")
 [1] 0.8760325
 > centre(x, "median")
 [1] 0.5360891
 > centre(x, "trimmed")
 [1] 0.6086504

ただし、これはif、それぞれに指定された一連のステートメントを持っていることと同じように見えますtype

これで全部switch()ですか?誰かが私にさらなる例とより良いアプリケーションを与えることができますか?


10
はい、それだけです。
Andrie、

回答:


118

さて、再び救助のタイミング。それswitchは一般的にifステートメントよりも速いようです。それはそうと、コードが持つ短い/すっきりであるという事実switchを支持する声明を傾いswitch

# Simplified to only measure the overhead of switch vs if

test1 <- function(type) {
 switch(type,
        mean = 1,
        median = 2,
        trimmed = 3)
}

test2 <- function(type) {
 if (type == "mean") 1
 else if (type == "median") 2
 else if (type == "trimmed") 3
}

system.time( for(i in 1:1e6) test1('mean') ) # 0.89 secs
system.time( for(i in 1:1e6) test2('mean') ) # 1.13 secs
system.time( for(i in 1:1e6) test1('trimmed') ) # 0.89 secs
system.time( for(i in 1:1e6) test2('trimmed') ) # 2.28 secs

更新ジョシュアのコメントを念頭に置いて、他の方法でベンチマークを試みました。マイクロベンチマークは最高のようです。...そしてそれは同様のタイミングを示しています:

> library(microbenchmark)
> microbenchmark(test1('mean'), test2('mean'), times=1e6)
Unit: nanoseconds
           expr  min   lq median   uq      max
1 test1("mean")  709  771    864  951 16122411
2 test2("mean") 1007 1073   1147 1223  8012202

> microbenchmark(test1('trimmed'), test2('trimmed'), times=1e6)
Unit: nanoseconds
              expr  min   lq median   uq      max
1 test1("trimmed")  733  792    843  944 60440833
2 test2("trimmed") 2022 2133   2203 2309 60814430

最終更新ここでは、用途の広さを示しますswitch

switch(type, case1=1, case2=, case3=2.5, 99)

これは、マップさcase2case3する2.5とする(無名の)デフォルト99。詳細については、?switch


3
このようなforループを使用すると、ガベージコレクションで問題が発生する可能性があります。ベンチマーク関数が優れているため、差ははるかに小さくなっていますbenchmark(test1('trimmed'), test2('trimmed'), replications=1e6)
ジョシュアウルリッヒ

@JoshuaUlrich ...どのbenchmark関数を使用していますか?「ベンチマーク」パッケージからの明らかなものではないようです。
トミー

1
stackoverflow.com/questions/6262203/によれば、「microbenchmark」はさらに優れたものです。
トミー

@JoshuaUlrich-からの結果で回答を更新しましたが、元の回答とmicrobencmark非常によく似ています。rbenchmarkがGCの問題をどのように回避するかは実際にはわかりませんが、evaland を呼び出すとオーバーヘッドが増えるようreplicateです。
トミー

余談ですが、同じ出力で複数のケースを持つことができますか?ieswitch(type, c(this,that)=do something)
LostLin、2011年

4

要するに、はい。ただし、どちらか一方を優先する場合があります。Googleの「ケーススイッチとそれ以外の場合」。SOについてもすでにいくつかの議論があります。また、MATLABのコンテキストでそれを説明する良いビデオもここにあります。

http://blogs.mathworks.com/pick/2008/01/02/matlab-basics-switch-case-vs-if-elseif/

個人的には、3つ以上のケースがある場合、通常はケース/スイッチを使用します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.