2014-01-03 3 views
5

У меня есть большой 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, так что все перестановки по Варс в результирующей разрушилась data.table?

ответ

3

Я бы также пойти с кросс-соединения, но будет использовать его в i -slot первоначального вызова [.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 

Этот подход упоминается как «по-без- от»и, как описано в ?data.table, это так же, как эффективно и быстро, как проходя группирования инструкции по by аргумента:

Дополнительно: Aggregation для подмножества известных групп особенно эффективно, когда передача входящих в группы «i». Когда 'i' является 'data.table', 'DT [i, j]' оценивает 'j' для каждой строки 'i'. Мы называем это без или группировка по i. Следовательно, самосоединение «DT [data.table (unique (colA)), j] 'равно , идентичное' DT [, j, by = colA] '.

+3

Только примечание: есть [FR здесь] (https://r-forge.r-project.org/tracker/index.php?func=detail&aid=2696&group_id=240&atid=978), и мы планируем переместите 'by-without-by' в' by'. То есть 'X [Y]' должен делать ** только соединение **, и если нужно реплицировать старое поведение, тогда нужно сделать: 'X [, j, by = Y, mult =, nomatch =] '(или что-то в этом роде). Это необходимо для сохранения согласованности с 'by', выполняющим задание' by' всегда и не загрязняемым 'i', делая' by' всего за 1 случай. – Arun

+0

Спасибо! Это прекрасно работает. Возвращает немного другой ответ (после игнорирования всех NA, которые он добавляет для отсутствующих перестановок), в том, что любые значения 'keycol', которые являются' NA', будут включать, но значение 'nv' будет' NA'. Я могу догадаться, почему это происходит, но может быть полезно вернуть предупреждение в этом случае. Решение состоит в том, чтобы заранее перекодировать 'NA' в 'keycol' vars. –

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 прямо сейчас, но вы можете легко изменить, что 0s, если вы хотите ,

Смежные вопросы