如何使用data.table
计算交互作用?具体而言,我正在尝试从右到左获取列的连续分组之间的所有唯一组合(删除未使用的级别)。我正在使用类似以下的代码:
## Sample data
set.seed(1999)
dat <- setDT(lapply(split(letters[1:9], 1:3), function(l) factor(sample(l, 10, TRUE, (1:3)^3))))
dat
# 1 2 3
# 1: d h i
# 2: g e f
# 3: g h i
# 4: g h i
# 5: d h i
# 6: g h c
# 7: d h i
# 8: g h f
# 9: g e i
# 10: d e i
## All factor combinations from left to right by column
f <- function(...) interaction(..., drop=TRUE)
levs <- Reduce(f, dat, accumulate = TRUE)
res <- unlist(lapply(levs, levels))
# [1] "d" "g" "d.e" "g.e" "d.h" "g.h" "g.h.c" "g.e.f" "g.h.f"
# [10] "d.e.i" "g.e.i" "d.h.i" "g.h.i"
其中res
是预期结果。它能正常工作,但我可以使用数据框架来代替,因为它没有充分利用内部的data.table匹配功能。
这只会使情况更糟,因为它重复了所有内容。
dat[, Reduce(f, .SD, accumulate = TRUE)]
我能用一个快速的data.table替换base的interaction
吗?
编辑
使用gglot2
的数据进行更大的示例。
data(diamonds, package="ggplot2")
dat <- as.data.table(diamonds)
sdcols <- c("cut", "color", "clarity") # some factor columns
## Expected output, really just interested in the levels,
## so character instead of factor is fine
levs <- unlist(Reduce(function(...) interaction(..., drop=TRUE),
dat[,sdcols,with=FALSE], accumulate = TRUE))
length(levels(levs)) # [1] 316
## Not quite right
levs2 <- dat[, Reduce(function(...) do.call(paste, c(list(...), sep=".")), .SD,
accumulate = TRUE), .SDcols=sdcols]
interaction
(它只需要组合因子水平并将它们粘在一起..?)需要很长时间。 - Frankset.seed(1); n = 1e5; etc
- FranksetDT(list(l1,l2))[, do.call(paste, c(.SD,sep=".")), by="V1,V2"]
或者没有by
的相同方式。在这里没有by
更快,因为你有 10 万行和 9 万个唯一的l1
xl2
组合;如果组合数少于行数,那么by
的方式会更快,我猜测是这样。 - Frank