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

Posted

技术标签:

【中文标题】使用 data.table[,,by=...] 时包括所有排列【英文标题】:Including all permutations when using data.table[,,by=...] 【发布时间】:2014-01-21 18:00:56 【问题描述】:

我有一个大的data.table,我正在使用,by 将其折叠到月级别。

有 5 个按变量,级别数为: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 var 的所有排列都在生成的折叠 data.table 中?

【问题讨论】:

【参考方案1】:

我也会使用交叉连接,但会在对 [.data.table 的原始调用的 i-slot 中使用它:

keycols <- c("g1", "g2", "g3")                       ## Grouping columns
setkeyv(dat, keycols)                                ## Set dat's key
ii <- do.call(CJ, sapply(dat[, ..keycols], 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 中传递这些组时特别有效。什么时候 idata.tableDT[i,j] 为每一行计算 ji。我们将其称为不带byi 分组。 因此,自加入DT[data.table(unique(colA)),j] 是 等同于DT[,j,by=colA]

【讨论】:

请注意:有一个FR here,我们计划将by-without-by 移动到by。也就是说,X[Y] 应该只是加入,如果想要复制旧的行为,那么需要这样做:X[, j, by=Y, mult=, nomatch=](或类似的东西)。这是为了保持与by 始终执行by 的工作的一致性,并且不会被i 污染在仅一种情况下执行by 谢谢!这很好用。返回一个稍微不同的答案(在忽略它为缺失排列添加的所有 NA 之后),因为任何 keycol 值是 NA 它将包括但 nv 的值将是 NA。我可以猜到为什么会发生这种情况,但在这种情况下返回警告可能会很好。解决方案只是预先在keycol vars 中重新编码NAs。【参考方案2】:

对唯一值进行笛卡尔连接,并使用它连接回您的结果

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。

【讨论】:

以上是关于使用 data.table[,,by=...] 时包括所有排列的主要内容,如果未能解决你的问题,请参考以下文章

R语言data.table导入数据实战:data.table使用by函数进行数据分组(aggregate)并获取分组的第一个数值或者最后一个数值

使用.BY,.GRP或其他方法添加data.table的多列聚合

R语言data.table导入数据实战:data.table设置键值(key)复合键设置删除键设置键值之后的数据连接(join)更加方便设置了键值之后可以使用keyby语法代替by语法

将继承范围与 data.table 中的 by 连接起来

如何根据多个by-record标准从data.table中提取特定字段?

使用 data.table 并行化/多线程