给定data.table
,如何找到它包含的唯一键的数量?
library(data.table)
z <- data.table(id=c(1,2,1,3),key="id")
length(unique(z$id))
==> 3
问题是unique
一般是二次,但是,由于data.table
中的密钥已排序,因此应该可以找到唯一密钥的数量线性时间中的data.table
。
答案 0 :(得分:7)
我会将我的评论扩展为答案。
向量上的 base::unique
(unique.default
)使用哈希表并且非常有效,平均复杂度为O(1) - 这很可能是一般情况。最坏的情况复杂度是O(n)。但是每次插入/搜索时发生这种情况的可能性极小 - 如果确实如此,它必须是一个糟糕的哈希函数。
在您的问题中,您只有一个关键列,因此基地的独特性应该非常高效。但是,在多个列上,unique.data.frame
的效率非常低 - 因为它会将所有列强制转换为字符,然后将它们粘贴在一起,然后在其上调用unique.default
。
您可以使用:
nrow(unique(z))
data.table的unique
方法默认情况下为其by
参数提供关键列。由于我们知道数据已经排序,而不是排序,我们使用data.table:::uniqlist
在O(n)
中更有效地获取对应于唯一行的索引。因此,它对任意数量的关键列都有效。
但是,我们可以在设置密钥时将此信息添加为属性,因为它非常简单。
答案 1 :(得分:2)
也许这个:
sum(Negate(duplicated)(z$id))
z $ id保持排序,因此重复可以更快地运行:
bigVec <- sample(1:100000, 30000000, replace=TRUE)
system.time( sum(Negate(duplicated)(bigVec)) )
user system elapsed
8.161 0.475 8.690
bigVec <- sort(bigVec)
system.time( sum(Negate(duplicated)(bigVec)) )
user system elapsed
0.00 2.09 2.10
但我只是检查并且长度(unique())在排序后的矢量上工作得更快......
所以也许有某种检查是否正在对矢量进行排序(可以在线性时间内完成)。对我来说,这看起来不是二次方的:
system.time( length(unique(bigVec)) )
user system elapsed
0.000 0.583 0.664
bigVec <- sort(sample(1:100000, 20000000, replace=TRUE))
system.time( length(unique(bigVec)) )
user system elapsed
0.000 1.290 1.242
bigVec <- sort(sample(1:100000, 30000000, replace=TRUE))
system.time( length(unique(bigVec)) )
user system elapsed
0.000 1.655 1.715