我有一个很大的data.table
我正在使用,by
折叠到月份级别。
有5个vars,等级为c(4,3,106,3,1380)
。 106是月,1380是地理单位。事实证明有一些0,因为有些单元格没有值。 by
放弃了这些,但我希望能保留它们。
可重复的例子:
require(data.table)
set.seed(1)
n <- 1000
s <- function(n,l=5) sample(letters[seq(l)],n,replace=TRUE)
dat <- data.table( x=runif(n), g1=s(n), g2=s(n), g3=s(n,25) )
datCollapsed <- dat[ , list(nv=.N), by=list(g1,g2,g3) ]
datCollapsed[ , prod(dim(table(g1,g2,g3))) ] # how many there should be: 5*5*25=625
nrow(datCollapsed) # how many there are
是否有一种有效的方法用0填充这些缺失值,以便所有by变量的排列都在最终的折叠data.table中?
答案 0 :(得分:3)
对唯一值进行笛卡尔连接,并使用它连接回结果
dat.keys <- dat[,CJ(g1=unique(g1), g2=unique(g2), g3=unique(g3))]
setkey(datCollapsed, g1, g2, g3)
nrow(datCollapsed[dat.keys]) # effectively a left join of datCollapsed onto dat.keys
# [1] 625
请注意,缺失值现在为NA,但如果需要,您可以轻松将其更改为0。
答案 1 :(得分:3)
我也会使用交叉加入,但会在i
的原始调用的[.data.table
- 插槽中使用它:
keycols <- c("g1", "g2", "g3") ## Grouping columns
setkeyv(dat, keycols) ## Set dat's key
ii <- do.call(CJ, sapply(dat[,keycols,with=FALSE], unique)) ## CJ() to form index
datCollapsed <- dat[ii, list(nv=.N)] ## Aggregate
## Check that it worked
nrow(datCollapsed)
# [1] 625
table(datCollapsed$nv)
# 0 1 2 3 4 5 6
# 135 191 162 82 39 13 3
这种方法被称为“by-without-by”,并且如?data.table
中所述,它与通过by
参数传递分组指令一样高效和快速:
高级:已知组子集的聚合是 在'i'中传递这些组时效率特别高。什么时候 'i'是'data.table','DT [i,j]'评估每行的'j' '我'。我们通过或按分组来调用此。 因此,自连接'DT [data.table(unique(colA)),j]'是 与'DT [,j,by = colA]'相同。