R 统计每个data.table行的出现次数
我有一个data.table太大,无法在RAM中熔化/铸造(数百万行) 从中,我需要提取每行没有重复值的行。重复的零和NA可以保留 在这个MWE中,“Duplicates”-列是我想要计算的R 统计每个data.table行的出现次数,r,data.table,R,Data.table,我有一个data.table太大,无法在RAM中熔化/铸造(数百万行) 从中,我需要提取每行没有重复值的行。重复的零和NA可以保留 在这个MWE中,“Duplicates”-列是我想要计算的 DT <- data.table(C1=c(0L, 7L, 0L, 0L), C2=c(0L, 0L, 0L, 4L), C3=c(2L, 0L, 2L, 3L), C4=c(0L, NA_integ
DT <- data.table(C1=c(0L, 7L, 0L, 0L),
C2=c(0L, 0L, 0L, 4L),
C3=c(2L, 0L, 2L, 3L),
C4=c(0L, NA_integer_, 2L, 6L),
C5=c(1L, 3L, 1L, 1L),
c6=c(0L, 4L, 2L, 4L),
Duplicates=c(FALSE, FALSE, TRUE, TRUE))
DT.wanted <- DT[Duplicates==FALSE, ]
DT这里有一个解决方案,应该还是稍微快一点(~3x)
foo_dup这里是另一个数据。表开始处理事情
DT[ lapply( data.table::transpose( DT ),
function(x) anyDuplicated( x[!is.na(x) & !x == 0] ) ) == 0, ]
不知道它如何保持记忆。。但是WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
基准
# Unit: microseconds
# expr min lq mean median uq max neval
# loop 11764.5 12164.2010 13987.589 12725.601 13775.0010 25885.601 100
# transpose 524.5 550.3515 592.633 566.601 597.4515 1116.201 100
基准代码
mydata <- data.table(C1=c(0L, 7L, 0L, 0L),
C2=c(0L, 0L, 0L, 4L),
C3=c(2L, 0L, 2L, 3L),
C4=c(0L, NA_integer_, 2L, 6L),
C5=c(1L, 3L, 1L, 1L),
C6=c(0L, 4L, 2L, 4L))
microbenchmark::microbenchmark(
loop = {
DT <- copy(mydata)
DT[, Duplicates:=FALSE]
for (i in 1L:nrow(DT)){
dt.i <- data.table(table(as.integer(DT[i, ])))
if (max(dt.i[V1>0, N])>1) DT[i, Duplicates:=TRUE]
}
},
transpose = {
DT <- copy(mydata)
DT[ lapply( transpose(DT), function(x) anyDuplicated( x[!is.na(x) & ! x == 0] ) ) == 0, ]
},times = 100L )
mydata这里是另一种使用基本R+数据的方法。table::rowidv
(大约是1mio数据行所选解决方案的8倍):
具有1e6行数据的计时:
mSD <- as.matrix(DT)
mSD[mSD==0L] <- NA_integer_
m <- cbind.data.frame(ROW=rep(1L:nrow(mSD), ncol(mSD)), COL=as.vector(mSD))
mcc <- m[complete.cases(m),]
dup <- unique(mcc$ROW[rowidv(mcc) > 1L])
DT[-dup]
Unit: seconds
expr min lq mean median uq max neval
mtd0(DT0) 9.902526 9.902526 9.902526 9.902526 9.902526 9.902526 1
mtd2(DT2) 1.234894 1.234894 1.234894 1.234894 1.234894 1.234894 1
我必须使用data.table
或者我可以使用其他pkg/base R吗?据我所知,只有data.table可以在不重写表的情况下执行此操作。没有足够的内存。这肯定会导致内存问题,但你可以结合这个独奏和我的循环。可能将data.table拆分为10个部分,并逐步应用此解决方案。是的,仍然需要大量内存。感谢您提供拆分data.table的提示
mSD <- as.matrix(DT)
mSD[mSD==0L] <- NA_integer_
m <- cbind.data.frame(ROW=rep(1L:nrow(mSD), ncol(mSD)), COL=as.vector(mSD))
mcc <- m[complete.cases(m),]
dup <- unique(mcc$ROW[rowidv(mcc) > 1L])
DT[-dup]
library(data.table)
set.seed(0L)
nr <- 1e5L
nc <- 6L
dat <- as.data.table(matrix(sample(c(0L:7L, NA_integer_), nr*nc, TRUE), nrow=nr))
DT0 <- copy(dat)
DT1 <- copy(dat)
DT2 <- copy(dat)
mtd0 <- function(DT) {
DT[ lapply(transpose(DT),
function(x) anyDuplicated( x[!is.na(x) & !x == 0] ) ) == 0, ]
}
mtd1 <- function(DT) {
foo_dup <- function(x) {
anyDuplicated(x[!is.na(x) & x != 0L]) != 0L
}
cols <- copy(names(DT))
for (i in 1L:nrow(DT)) {
set(DT, i, "Duplicates", foo_dup(unlist(DT[i, ..cols])) )
}
}
mtd2 <- function(DT) {
mSD <- as.matrix(DT)
mSD[mSD==0L] <- NA_integer_
m <- cbind.data.frame(ROW=rep(1L:nrow(mSD), ncol(mSD)), COL=as.vector(mSD))
mcc <- m[complete.cases(m),]
dup <- unique(mcc$ROW[rowidv(mcc) > 1L])
DT[-dup]
}
microbenchmark::microbenchmark(times=1L, mtd0(DT0), mtd1(DT1), mtd2(DT2))
Unit: milliseconds
expr min lq mean median uq max neval
mtd0(DT0) 999.47159 999.47159 999.47159 999.47159 999.47159 999.47159 1
mtd1(DT1) 110725.50423 110725.50423 110725.50423 110725.50423 110725.50423 110725.50423 1
mtd2(DT2) 64.79497 64.79497 64.79497 64.79497 64.79497 64.79497 1
Unit: seconds
expr min lq mean median uq max neval
mtd0(DT0) 9.902526 9.902526 9.902526 9.902526 9.902526 9.902526 1
mtd2(DT2) 1.234894 1.234894 1.234894 1.234894 1.234894 1.234894 1