Пустые факторы в таблице data.table

У меня есть таблица данных, в которой есть факторный столбец с пустыми уровнями. Мне нужно получить количество строк и суммы других переменных, сгруппированных по нескольким факторам, включая фактор с пустыми уровнями. Мой вопрос похож на этот один, но здесь мне нужно учитывать несколько факторов.

Например, пусть data.table будет:

library('data.table')

dtr <- data.table(v1=sample(1:15), 
v2=factor(sample(letters[1:3], 15, replace = TRUE),levels=letters[1:5]),
v3=sample(c("yes", "no"), 15, replace = TRUE))

Я хочу сделать следующее:

dtr[,list(freq=.N,mm=sum(v1,na.rm=T)),by=list(v2,v3)]

#Output is:
   v2  v3 freq mm
1:  b yes    4 22
2:  b  no    1 13
3:  c  no    3 10
4:  a  no    4 49
5:  c yes    1 10
6:  a yes    2 16

Я хочу, чтобы выходные данные включали также пустые уровни для v2 («d» и «e»), как в table(dtr$v2,dtr$v3), поэтому окончательный результат должен выглядеть так (порядок не имеет значения):

   v2  v3 freq mm
1:  b yes    4 22
2:  b  no    1 13
3:  c  no    3 10
4:  a  no    4 49
5:  c yes    1 10
6:  a yes    2 16
7:  d yes    0 0
8:  d no    0 0
9:  e yes    0 0
10:  e no    0 0

Я попытался использовать метод, использованный в ссылке, но я не уверен, как использовать объединенную функцию J (), когда используется несколько столбцов.

Это отлично подходит для группировки только по 1 столбцу:

setkey(dtr,v2)
dtr[J(levels(v2)),list(freq=.N,mm=sum(v1,na.rm=T))]

Однако dtr[J(levels(v2),v3),list(freq=.N,mm=sum(v1,na.rm=T))] не включает все комбинации


person Asayat    schedule 18.09.2013    source источник
comment
Я обнаружил, что если я изменю порядок значений и установлю setkey(dtr,v3,v2) и unique(dtr[J(v3,levels(v2)),list(freq=.N,mm=sum(v1,na.rm=T))]), это будет работать, но может ли кто-нибудь объяснить, почему и будет ли это работать для таблицы больших данных с более чем двумя группами?   -  person Asayat    schedule 18.09.2013
comment
Спасибо @Asayat. Я подал FR № 4914 здесь: r-forge.r-project.org/tracker/   -  person Arun    schedule 18.09.2013


Ответы (2)


library(data.table)
set.seed(42)
dtr <- data.table(v1=sample(1:15), 
                  v2=factor(sample(letters[1:3], 15, replace = TRUE),levels=letters[1:5]),
                  v3=sample(c("yes", "no"), 15, replace = TRUE))

res <- dtr[,list(freq=.N,mm=sum(v1,na.rm=T)),by=list(v2,v3)]

Вы можете использовать CJ (перекрестное соединение). Выполнение этого после агрегирования позволяет избежать установки ключа для большой таблицы и должно быть быстрее.

setkey(res,c("v2","v3"))
res[CJ(levels(dtr[,v2]),unique(dtr[,v3])),]

#    v2  v3 freq mm
# 1:  a  no    1  9
# 2:  a yes    2 11
# 3:  b  no    2 11
# 4:  b yes    3 23
# 5:  c  no    4 40
# 6:  c yes    3 26
# 7:  d  no   NA NA
# 8:  d yes   NA NA
# 9:  e  no   NA NA
# 10:  e yes   NA NA
person Roland    schedule 18.09.2013
comment
с ›5 * 10 ^ 6 строками и› 300 уровнями фактора tapply будет работать вечно :) - person Asayat; 18.09.2013
comment
@Arun Со статистической точки зрения имеет смысл обрабатывать такие пустые уровни факторов. - person Roland; 18.09.2013
comment
@Asayat Нет, Арун говорит об улучшении таблицы данных для обработки таких факторов, как tapply. - person Roland; 18.09.2013
comment
Извините, @Arun, только что понял :) жаль, что у меня нет пакета data.table, чтобы справиться с этим :) - person Asayat; 18.09.2013

table() также будет фиксировать нулевые значения частоты. Чтобы получить столбец «мм», вы можете выполнить простое соединение. Например,

library(data.table)
set.seed(42)
dtr <- data.table(v1=sample(1:15), 
                  v2=factor(sample(letters[1:3], 15, replace = TRUE),levels=letters[1:5]),
                  v3=sample(c("yes", "no"), 15, replace = TRUE))
res <- as.data.table(dtr[,table(v2,v3)])
setnames(res,'N','freq')
setkey(res,v2,v3)
setkey(dtr,v2,v3)
res <- dtr[,.(mm=sum(v1,na.rm=TRUE)),by=c('v2','v3')][res]

Я не уверен, насколько table() тесты с перекрестным соединением.

person jeromeResearch    schedule 25.09.2018