data.table有效的重复计数

时间:2017-08-29 23:17:27

标签: r performance data.table

使用data.table我可以使用unique(mydt)告诉我哪些行是唯一的行。我有兴趣了解一行重复的次数。例如

require(data.table)

data.table(x = c('a', 'a', 'a', 'b', 'b'),
           y = c(1, 1, 2, 3, 4))

应该找出唯一的行

   x y
1: a 1
2: a 2
3: b 3
4: b 4

并且行(a,1)有2个重复的行。到目前为止,我已经提出了

mydt.colnames = colnames(mydt)
mydt.fweighted = mydt[,
                      list(fweight = .N),
                      by = mydt.colnames]

但这似乎很慢,并且它根本没有使用独特的功能。是否有一种快速的方法来实现这一点?

2 个答案:

答案 0 :(得分:0)

试试这个:

require(data.table)
data.table(x = c('a', 'a', 'a', 'b', 'b'),
           y = c(1, 1, 2, 3, 4))

sapply(1:nrow(unique(Table[,1])), function(x) 
length(which(Table[,1] == as.character(unique(Table[,1])[x]))))

对于你的例子,这对我有用

答案 1 :(得分:0)

测试更大的数据集:

n <- 2e6
set.seed(1)
mydt <- data.table(x = sample(LETTERS, n, replace = T),
                   y = sample(1:10, n, replace = T))


JCWong <- function(mydt) {
  mydt.colnames <- colnames(mydt)
  mydt.fweighted <- mydt[, list(N = .N), by = mydt.colnames]
  mydt.fweighted
}

thelatemail <- function(mydt) {
  mydt.fweighted2 <- mydt[unique(mydt), on = colnames(mydt), .N, by = .EACHI]
  mydt.fweighted2
}

all.equal(JCWong(mydt),  thelatemail(mydt))
# [1] TRUE

require(microbenchmark)
microbenchmark(JCWong(mydt),  thelatemail(mydt))
# Unit: milliseconds
#              expr      min       lq     mean   median       uq       max neval cld
#      JCWong(mydt) 32.80524 33.49849 35.22232 34.11636 35.70609  47.31256   100  a 
# thelatemail(mydt) 56.55455 57.38479 61.51967 58.05206 59.51973 124.02087   100   b

增加列数:

mydt
new <- replicate(30, sample(1:10, n, replace = T))
mydt <- cbind(mydt, as.data.table(new))
all.equal(JCWong(mydt),  thelatemail(mydt))

system.time(JCWong(mydt)) #0.85 
system.time(thelatemail(mydt)) #7.05 

tr <- microbenchmark(JCWong(mydt),  thelatemail(mydt), times = 10)
ggplot2::autoplot(tr)
# Unit: milliseconds
#              expr       min       lq      mean    median        uq       max neval cld
#      JCWong(mydt)  817.0644  830.729  866.6022  866.8088  878.4169  982.3655    10  a 
# thelatemail(mydt) 6944.5352 7083.121 7203.8255 7186.6229 7241.6905 7518.9050    10   b

看起来你的方法非常快。也许您可以描述数据的大小?