素晴らしい質問です。はい、apply
by 行はページ効率的ではありません。 は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()
(非プリミティブでベクトル化された関数)10
nrow(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
>