4

data.table現在、パッケージングに慣れようとしていますR1データテーブルの各行で最後に発生したインデックスを取得し、aその新しい列をに追加したいとしaます。これに対する私のコードは次のとおりです。

  a = data.table(matrix(sample(c(0,1),500,rep=T),50,10))
  a[,ind:=apply(a==1,1,function(x) max(which(x)))]

data.tableそれにもかかわらず、これはより多くの構文を使用して短い方法で記述できると思います。したがって、私の質問は次のとおりです。のコンポーネントapply内の関数なしでこれを行う方法は?j[

4

1 に答える 1

3

素晴らしい質問です。はい、applyby 行はページ効率的ではありません。 はwhichすべての行に割り当てられ、 は とa==1同じ大きさの新しい論理行列を作成しaます。

ではdata.table、列ごとに処理を行います。 場合によっては、列をループするのがdata.table好きですfor(行をループしないでforください):

a[,ans:=0L]
for (i in 1:10) set(a,which(a[[i]]==1),"ans",i)

identical(a$ind, a$ans)
# [1] TRUE

ご覧のとおり、まったく異なるスタイルです。しかし、私は、これは次のようにすべきだと思います:

  • ページ効率的; つまり、メモリ内で連続する列によって実行されます
  • の全体ではなく、1 列 (ちょうど) のワーキング メモリが必要です。a
  • 時間ではなく呼び出しwhich()(非プリミティブでベクトル化された関数)10nrow(a)

ただし、速度テストは行っていないので、言葉を使わなければならないかもしれません.

を参照してください?set

コメントに応答して、それがどのように機能するかを調べるために、setたまたま へのポインターを返すdata.tableため、進行中に最初の数行を確認できます。

a[,ans:=0L]   # add column by reference, initialized with 0L

> head(a)
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 ans
1:  0  0  1  0  1  1  0  1  1   1   0
2:  0  0  1  1  0  0  1  1  1   1   0
3:  0  1  0  0  0  1  1  1  1   0   0
4:  0  0  0  1  1  0  1  1  1   1   0
5:  1  1  1  1  0  0  0  0  0   1   0
6:  1  1  0  1  1  0  1  0  1   1   0

うまくいけば、以下はそれがどのように機能しているかを明らかにします:

> for (i in 1:10) print(head(set(a,which(a[[i]]==1),"ans",i)))
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 ans
1:  0  0  1  0  1  1  0  1  1   1   0
2:  0  0  1  1  0  0  1  1  1   1   0
3:  0  1  0  0  0  1  1  1  1   0   0
4:  0  0  0  1  1  0  1  1  1   1   0
5:  1  1  1  1  0  0  0  0  0   1   1
6:  1  1  0  1  1  0  1  0  1   1   1
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 ans
1:  0  0  1  0  1  1  0  1  1   1   0
2:  0  0  1  1  0  0  1  1  1   1   0
3:  0  1  0  0  0  1  1  1  1   0   2
4:  0  0  0  1  1  0  1  1  1   1   0
5:  1  1  1  1  0  0  0  0  0   1   2
6:  1  1  0  1  1  0  1  0  1   1   2
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 ans
1:  0  0  1  0  1  1  0  1  1   1   3
2:  0  0  1  1  0  0  1  1  1   1   3
3:  0  1  0  0  0  1  1  1  1   0   2
4:  0  0  0  1  1  0  1  1  1   1   0
5:  1  1  1  1  0  0  0  0  0   1   3
6:  1  1  0  1  1  0  1  0  1   1   2
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 ans
1:  0  0  1  0  1  1  0  1  1   1   3
2:  0  0  1  1  0  0  1  1  1   1   4
3:  0  1  0  0  0  1  1  1  1   0   2
4:  0  0  0  1  1  0  1  1  1   1   4
5:  1  1  1  1  0  0  0  0  0   1   4
6:  1  1  0  1  1  0  1  0  1   1   4
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 ans
1:  0  0  1  0  1  1  0  1  1   1   5
2:  0  0  1  1  0  0  1  1  1   1   4
3:  0  1  0  0  0  1  1  1  1   0   2
4:  0  0  0  1  1  0  1  1  1   1   5
5:  1  1  1  1  0  0  0  0  0   1   4
6:  1  1  0  1  1  0  1  0  1   1   5
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 ans
1:  0  0  1  0  1  1  0  1  1   1   6
2:  0  0  1  1  0  0  1  1  1   1   4
3:  0  1  0  0  0  1  1  1  1   0   6
4:  0  0  0  1  1  0  1  1  1   1   5
5:  1  1  1  1  0  0  0  0  0   1   4
6:  1  1  0  1  1  0  1  0  1   1   5
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 ans
1:  0  0  1  0  1  1  0  1  1   1   6
2:  0  0  1  1  0  0  1  1  1   1   7
3:  0  1  0  0  0  1  1  1  1   0   7
4:  0  0  0  1  1  0  1  1  1   1   7
5:  1  1  1  1  0  0  0  0  0   1   4
6:  1  1  0  1  1  0  1  0  1   1   7
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 ans
1:  0  0  1  0  1  1  0  1  1   1   8
2:  0  0  1  1  0  0  1  1  1   1   8
3:  0  1  0  0  0  1  1  1  1   0   8
4:  0  0  0  1  1  0  1  1  1   1   8
5:  1  1  1  1  0  0  0  0  0   1   4
6:  1  1  0  1  1  0  1  0  1   1   7
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 ans
1:  0  0  1  0  1  1  0  1  1   1   9
2:  0  0  1  1  0  0  1  1  1   1   9
3:  0  1  0  0  0  1  1  1  1   0   9
4:  0  0  0  1  1  0  1  1  1   1   9
5:  1  1  1  1  0  0  0  0  0   1   4
6:  1  1  0  1  1  0  1  0  1   1   9
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 ans
1:  0  0  1  0  1  1  0  1  1   1  10
2:  0  0  1  1  0  0  1  1  1   1  10
3:  0  1  0  0  0  1  1  1  1   0   9
4:  0  0  0  1  1  0  1  1  1   1  10
5:  1  1  1  1  0  0  0  0  0   1  10
6:  1  1  0  1  1  0  1  0  1   1  10
> 
于 2012-08-13T22:22:44.270 に答える