如何有效地计算data.table的唯一(数字)列向量?

rma*_*gno 3 r data.table

foo <- data.table(x = 1:5/sum(1:5),
                  y = (-4):0/sum((-4):0),
                 z1 = 2:6/sum(2:6),
                 z2 = 2:6/sum(2:6))
Run Code Online (Sandbox Code Playgroud)

假设我有foo数据表(如上所述):

            x   y   z1   z2
1: 0.06666667 0.4 0.10 0.10
2: 0.13333333 0.3 0.15 0.15
3: 0.20000000 0.2 0.20 0.20
4: 0.26666667 0.1 0.25 0.25
5: 0.33333333 0.0 0.30 0.30
Run Code Online (Sandbox Code Playgroud)

如何有效地计算唯一列?在这种情况下只有3.

请假设一般:

  1. foo始终是数据表而不是矩阵; 虽然列总是数字.
  2. foo 实际上很大,nrow> 20k,ncol> 100

是否可以在不制作额外数据副本的情况下执行此操作?

我目前的方法是使用applypaste来获取每列的单个值,然后length(unique(.))对结果执行...

是否有任何魔法data.table::transpose(),data.table::uniqueN也许还有其他朋友?

Jaa*_*aap 5

另一种可能性

length(unique(as.list(foo)))
Run Code Online (Sandbox Code Playgroud)

这给出了预期的结果:

> length(unique(as.list(foo)))
[1] 3
Run Code Online (Sandbox Code Playgroud)

注意:必须使用,length(unique())因为uniqueN()它将返回错误.

根据@Ryan的评论,你也可以这样做:

length(unique.default(foo))
Run Code Online (Sandbox Code Playgroud)

关于速度,两种方法都是可比较的(当在更大的5M行数据集上测量时):

> fooLarge <- foo[rep(1:nrow(foo),1e6)]
> microbenchmark(length(unique.default(fooLarge)), length(unique(as.list(fooLarge))))
Unit: milliseconds
                              expr     min       lq     mean   median       uq       max neval cld
  length(unique.default(fooLarge)) 94.0433 94.56920 95.24076 95.01492 95.67131 103.15433   100   a
 length(unique(as.list(fooLarge))) 94.0254 94.68187 95.17648 95.02672 95.49857  99.19411   100   a
Run Code Online (Sandbox Code Playgroud)

如果您只想保留唯一列,可以使用:

# option 1
cols <- !duplicated(as.list(foo))
foo[, ..cols]

# option 2 (doesn't retain the column names)
as.data.table(unique.default(foo))
Run Code Online (Sandbox Code Playgroud)

给出(显示输出选项1):

            x   y   z1
1: 0.06666667 0.4 0.10
2: 0.13333333 0.3 0.15
3: 0.20000000 0.2 0.20
4: 0.26666667 0.1 0.25
5: 0.33333333 0.0 0.30
Run Code Online (Sandbox Code Playgroud)

  • 看看`methods('unique')`,你可以做`length(unique.default(foo))`来避免`as.list`.如果as.list创建一个我不确定的副本,那将是值得做的. (2认同)