17

以前、R でのベクトルの考え方に関する自分自身の質問に答えましたが、「ベクトル化」できない別の問題があります。ベクトルの方が高速でループが遅いことは知っていますが、ベクトル メソッドでこれを行う方法がわかりません。

完全な限界分析を行いたいデータ フレーム (感傷的な理由から my.data と呼びます) があります。特定の要素を一度に 1 つずつ削除し、データ フレームを「値」にする必要があります。次に、次の要素のみを削除して、繰り返しを再度実行する必要があります。その後、何度も何度も... アイデアは、私のデータのサブセットに対して完全な周辺分析を行うことです。とにかく、これをベクトル効率の良い方法で行う方法が思いつきません。

コードのループ部分を短くすると、次のようになります。

for (j in my.data$item[my.data$fixed==0]) { # <-- selects the items I want to loop 
                                            #     through
    my.data.it <- my.data[my.data$item!= j,] # <-- this kicks item j out of the list
    sum.data <-aggregate(my.data.it, by=list(year), FUN=sum, na.rm=TRUE) #<-- do an
                                                                         # aggregation

    do(a.little.dance) && make(a.little.love) -> get.down(tonight) # <-- a little
                                                                   #  song and dance

    delta <- (get.love)                                         # <-- get some love
    delta.list<-append(delta.list, delta, after=length(delta.list)) #<-- put my love
                                                                    #    in a vector 
}

だから明らかに、私は途中でたくさんのものをハックしました。目標は、より効率的なベクトルを使用して j ループを削除することです。何か案は?

4

3 に答える 3

9

不思議なことに、Rでベクトル化することを学ぶことは、基本的な関数型プログラミングに慣れるのに役立ちました。基本的な手法は、ループ内の操作を関数として定義することです。

data = ...;
items = ...;

leave_one_out = function(i) {
   data1 = data[items != i];
   delta = ...;  # some operation on data1
   return delta;
}


for (j in items) {
   delta.list = cbind(delta.list, leave_one_out(j));
}

ベクトル化するには、forループをsapplyマッピング関数に置き換えるだけです。

delta.list = sapply(items, leave_one_out);
于 2009-05-07T09:54:05.627 に答える
9

これは、合計を生成するための別の非常にRタイプの方法のように見えるものです。入力ベクトルと同じ長さのベクトルを生成します。このベクトルには、n個の要素の繰り返しの合計しか含まれていません。次に、合計ベクトルから元のベクトルを減算します。結果:各エントリが元のベクトルからi番目の要素を差し引いたベクトル(isums)。

> (my.data$item[my.data$fixed==0])
[1] 1 1 3 5 7
> sums <- rep(sum(my.data$item[my.data$fixed==0]),length(my.data$item[my.data$fixed==0]))
> sums
[1] 17 17 17 17 17
> isums <- sums - (my.data$item[my.data$fixed==0])
> isums
[1] 16 16 14 12 10
于 2009-01-18T15:12:24.020 に答える
0

これは答えではありませんが、この方向に洞察があるかどうかは疑問です。

> tapply((my.data$item[my.data$fixed==0])[-1], my.data$year[my.data$fixed==0][-1], sum)

tapply は、2 番目の引数として指定されたパラメーターによってグループ化された統計 (この場合は合計、3 番目の引数) のテーブルを生成します。例えば

2001 2003 2005 2007
1    3    5    7

[-1] 表記は、選択した行から観測 (行) を 1 つ削除します。したがって、ループして各ループで [-i] を使用できます

for (i in 1:length(my.data$item)) {
  tapply((my.data$item[my.data$fixed==0])[-i], my.data$year[my.data$fixed==0][-i], sum)
}

観測値が 1 つしかない年がある場合、連続する tapply 呼び出しによって返されるテーブルには、同じ数の列が含まれないことに注意してください。(つまり、2001 年の唯一の観測を除外すると、2003、2005、および 2007 の列のみが返されます)。

于 2009-01-16T20:12:55.747 に答える