使用data.table [,, by = ...]时包括所有排列

时间:2014-01-03 23:01:40

标签: r data.table collapse

我有一个很大的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中?

2 个答案:

答案 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]'相同。