9

Rの教科書は、ループの代わりにラップの使用を促進し続けています。これは、次のような引数を持つ関数でも簡単です。

lapply(somelist, f, a=1, b=2) 

しかし、リスト要素に応じて引数が変わるとどうなりますか?私のsomelistが次のもので構成されていると仮定します。

somelist$USA
somelist$Europe
somelist$Switzerland

さらにanotherlist、同じリージョンがあり、これらの変化する引数を重ねて使用したいですか?これは、たとえばfが比率計算の場合に役立ちます。

lapply(somelist, f, a= somelist$USA, b=anotherlist$USA) 

これらの領域を効率的に実行するループ以外の方法はありますか?

編集:私の問題は、以前に作成した関数をインデックスなしで使用しようとしたことのようです...

ratio <-function(a,b){
z<-(b-a)/a
return(z)
}

につながった

lapply(data,ratio,names(data))

これは機能しません。たぶん他の人もこの間違いから学ぶことができます。

4

2 に答える 2

16

リスト要素ではなくリスト名に適用します。例えば:

somelist <- list('USA'=rnorm(10), 'Europe'=rnorm(10), 'Switzerland'=rnorm(10))
anotherlist <- list('USA'=5, 'Europe'=10, 'Switzerland'=4)
lapply(names(somelist), function(i) somelist[[i]] / anotherlist[[i]])

編集:

また、これを「効率的に」行うための「ループを除く」方法があるかどうかも尋ねます。apply が必ずしもより効率的であるとは限らないことに注意してください。効率は、おそらくあなたの内部機能がどれほど速いかによって決まります. リストの各要素を操作したい場合は、 apply() 呼び出しで隠されているかどうかにかかわらず、ループが必要になります。この質問を確認してください: R の適用ファミリは構文上の砂糖以上のものですか?

上記の例は、for ループとして書き直すことができ、簡単なベンチマークを作成できます。

fun1 <- function(){
    lapply(names(somelist), function(i) somelist[[i]] / anotherlist[[i]])
}
fun2 <- function(){
    for (i in names(somelist)){
        somelist[[i]] <- somelist[[i]] / anotherlist[[i]] 
    }
    return(somelist)
}
library(rbenchmark)

benchmark(fun1(), fun2(),
          columns=c("test", "replications",
          "elapsed", "relative"),
          order="relative", replications=10000)

私のマシンでのベンチマークの出力は次のとおりです。

    test replications elapsed relative
1 fun1()        10000   0.145 1.000000
2 fun2()        10000   0.148 1.020690

これは実際の作業アプリケーションではなく、関数も現実的なタスクではありませんが、計算時間の差はごくわずかであることがわかります。

于 2011-06-06T14:22:48.947 に答える
7

あなたはただ何をlapply()やり直すかを考え出す必要があります。ここでは、さまざまな引数を取るnames()ように書き直した後、リストのうちの1つで十分です。f()

somelist <- list(USA = 1:10, Europe = 21:30,
                 Switzerland = seq(1, 5, length = 10))
anotherlist <- list(USA = list(a = 1, b = 2), Europe = list(a = 2, b = 4),
                    Switzerland = list(a = 0.5, b = 1))

f <- function(x, some, other) {
    (some[[x]] + other[[x]][["a"]]) * other[[x]][["b"]]
}

lapply(names(somelist), f, some = somelist, other = anotherlist)

与える:

R> lapply(names(somelist), f, some = somelist, other = anotherlist)
[[1]]
 [1]  4  6  8 10 12 14 16 18 20 22

[[2]]
 [1]  92  96 100 104 108 112 116 120 124 128

[[3]]
 [1] 1.500000 1.944444 2.388889 2.833333 3.277778 3.722222 4.166667 4.611111
 [9] 5.055556 5.500000
于 2011-06-06T14:28:15.370 に答える