R, Дополнение по агрегированию data.table

Можно ли агрегировать с дополнением в R data.tables. Пример ниже.

library(data.table)
dt <- data.table(a=c("word1","word2","word2","word2"), b=c("cat1","cat1","cat1","cat2"))

Чтобы получить количество конкретных слов в категории

newdt <- dt[,(.N),by=.(a,b)]
#word1,cat1 - 1
#word2,cat1 - 2
#word2,cat2 - 1

Как я могу посчитать количество всех других слов в категории? Или, соответственно, количество других категорий, в которых находится это слово? Что-то вроде следующего?

#doesn't work
#newdt2 <- dt[a!=a,(.N),by=.(a,b)]
#the expected answer would be
#word1,cat1 - 2
#word2,cat1 - 1
#word2,cat2 - 0

Я не могу найти никакой помощи по этому вопросу в онлайн-учебниках или вопросах. Есть ли простой способ получить дополнение. Решение Data.table было бы хорошо, так как работа с таблицей строк 50M. Спасибо!

2 ответа

Решение

Следуя идее Бруно, вычислить разницу общего количества по категориям за вычетом количества слов в каждой категории, но используя data.table Синтаксис с обновлением при соединении становится "однострочным":

library(data.table)
dt <-data.table(a = c("word1", rep("word2", 3L)), b = c(rep("cat1", 3L), "cat2"))
dt[, .N, by = .(a, b)][dt[, .N, by = b], on = "b", Nc := i.N - N][]
       a    b N Nc
1: word1 cat1 1  2
2: word2 cat1 2  1
3: word2 cat2 1  0

Ниже приведен ваш код (я добавил двойные кавычки, чтобы он работал):

library(data.table)
dt <-
 data.table(a=c("word1","word2","word2","word2"),b=c("cat1","cat1","cat1","cat2"))

newdt <- dt[,(.N),by=.(a,b)]
names(newdt) = c("a", "b", "cnt") # rename the count column

Следующая строка подсчитывает, сколько раз появляется каждая категория

catCnt = dt[,(.N),by=.(b)]
names(catCnt) = c("b", "tot_b")
catCnt

Количество слов, принадлежащих каждой категории, кроме текущего слова, представляет собой разницу между количеством слов, принадлежащих к категории, и количеством раз, которое пара (category, word) появляется. Чтобы достичь результата, я объединяю два data.table объекты по столбцу категории

aux = merge(newdt, catCnt, by="b")

а затем я вычисляю разницу между общим количеством и количеством "пар":

aux$cnt_not_a = aux$tot_b - aux$cnt

Если вы хотите сохранить только необходимый столбец:

res = aux[, c("b", "a", "cnt_not_a")]
res

Я не знаю, если вы можете достичь этого с помощью data.table только команды, но это выглядит довольно просто для меня...

Другие вопросы по тегам