好问题。是的apply
,逐行不是页面效率,which
将为每一行分配,并a==1
创建一个新的逻辑矩阵,大小为a
.
在data.table
我们按列做事。 有时,data.table
使用for
列循环(从不for
循环行)是-ish:
a[,ans:=0L]
for (i in 1:10) set(a,which(a[[i]]==1),"ans",i)
identical(a$ind, a$ans)
# [1] TRUE
如您所见,这是一种完全不同的风格。但是,我认为,这应该是:
- 页面高效;即,它按内存中连续的列运行
- 需要与(仅)一列而不是整列一样大的工作内存
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
>