我的data.table有多少个唯一键?

时间:2014-10-27 17:20:30

标签: r data.table

给定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

2 个答案:

答案 0 :(得分:7)

我会将我的评论扩展为答案。

向量上的

base::uniqueunique.default)使用哈希表并且非常有效,平均复杂度为O(1) - 这很可能是一般情况。最坏的情况复杂度是O(n)。但是每次插入/搜索时发生这种情况的可能性极小 - 如果确实如此,它必须是一个糟糕的哈希函数。

在您的问题中,您只有一个关键列,因此基地的独特性应该非常高效。但是,在多个列上,unique.data.frame的效率非常低 - 因为它会将所有列强制转换为字符,然后将它们粘贴在一起,然后在其上调用unique.default

您可以使用:

nrow(unique(z))

data.table的unique方法默认情况下为其by参数提供关键列。由于我们知道数据已经排序,而不是排序,我们使用data.table:::uniqlistO(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