Включая все перестановки при использовании data.table [, by =...]
У меня есть большой 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, так что все перестановки из vars находятся в результирующем сложенном data.table?
Ответы
Ответ 1
Я бы тоже пошел с перекрестным соединением, но использовал бы его в i
-слоте исходного вызова [.data.table
:
keycols <- c("g1", "g2", "g3") ## Grouping columns
setkeyv(dat, keycols) ## Set dat 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" для каждой строки из 'i'. Мы называем это без или группированием по i. Следовательно, self join 'DT [data.table(unique (colA)), j]' является идентичный 'DT [, j, by = colA]'.
Ответ 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 прямо сейчас, но вы можете легко изменить это на 0s, если хотите.