4

我目前正在尝试习惯data.tableR. 我想获取1数据表每一行中最后一次出现的索引,比如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

好问题。是的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
> 
于 2012-08-13T22:22:44.270 回答