How does one compute interactions using data.table? Specifically, I am trying to get all the unique combinations between successive groupings of columns from right to left (dropping unused levels). I am using code like this,
## 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"
where res is the intended result. It works fine, but I might as well just be using a data.frame since this isn't advantage of any of the internal data.table matching.
This is just worse cause it repeats everything.
dat[, Reduce(f, .SD, accumulate = TRUE)]
Can I replace base's interaction with a fast data.table one?
Edit
a larger example with data from 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(which just needs to compose combns of factor levels and paste them together..?) to take much time. - Frankinteractionsshould be able to subsist on just thelevelsattribute, eh; why would it need the whole vector? Anyway, since this is a question of performance, maybe you can add an example that takes longer to run.set.seed(1); n = 1e5; etc- FranksetDT(list(l1,l2))[, do.call(paste, c(.SD,sep=".")), by="V1,V2"]or the same thing without aby. Withoutbyis faster here just because you have 100k rows and 90k unique combos ofl1xl2; thebyway would win if you had fewer combos vs rows, I guess. - Frank