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.
请假设一般:
foo始终是数据表而不是矩阵; 虽然列总是数字.foo 实际上很大,nrow> 20k,ncol> 100是否可以在不制作额外数据副本的情况下执行此操作?
我目前的方法是使用apply列paste来获取每列的单个值,然后length(unique(.))对结果执行...
是否有任何魔法data.table::transpose(),data.table::uniqueN也许还有其他朋友?
另一种可能性
length(unique(as.list(foo)))
Run Code Online (Sandbox Code Playgroud)
这给出了预期的结果:
Run Code Online (Sandbox Code Playgroud)> length(unique(as.list(foo))) [1] 3
注意:必须使用,length(unique())因为uniqueN()它将返回错误.
根据@Ryan的评论,你也可以这样做:
length(unique.default(foo))
Run Code Online (Sandbox Code Playgroud)
关于速度,两种方法都是可比较的(当在更大的5M行数据集上测量时):
Run Code Online (Sandbox Code Playgroud)> 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
如果您只想保留唯一列,可以使用:
# 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):
Run Code Online (Sandbox Code Playgroud)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