Проверьте частоту значения data.table в других data.table

 library(data.table)
 DT1 <- data.table(num = 1:6, group = c("A", "B", "B", "B", "A", "C"))
 DT2 <- data.table(group = c("A", "B", "C"))

Я хочу добавить столбец popular в DT2 со значением TRUE, если DT2$group содержится в DT1$group не менее двух раз. Итак, в приведенном выше примере DT2 должен быть

    group popular
 1:     A    TRUE
 2:     B    TRUE
 3:     C   FALSE

Каким будет эффективный способ добраться до этого?

Пример: DT2 может содержать больше групп, чем DT1, поэтому здесь приведен пример:

 DT1 <- data.table(num = 1:6, group = c("A", "B", "B", "B", "A", "C"))
 DT2 <- data.table(group = c("A", "B", "C", "D"))

И желаемый результат будет

    group popular
 1:     A    TRUE
 2:     B    TRUE
 3:     C   FALSE
 4:     D   FALSE

Ответ 1

Я просто делаю так:

## 1.9.4+
setkey(DT1, group)
DT1[J(DT2$group), list(popular = .N >= 2L), by = .EACHI]
#    group popular
# 1:     A    TRUE
# 2:     B    TRUE
# 3:     C   FALSE
# 4:     D   FALSE ## on the updated example
Синтаксис соединения

data.table довольно прост, при этом, присоединяясь, вы также можете агрегировать/выбрать/обновить столбцы в j. Здесь мы выполняем соединение. Для каждой строки в DT2$group, в соответствующих совпадающих строках в DT1, мы вычисляем j -expression .N >= 2L; указав by = .EACHI (пожалуйста, проверьте 1.9.4 NEWS), мы вычисляем j -выражение каждый раз.


В 1.9.4, .() был введен как псевдоним во всех i, j и by. Таким образом, вы также можете:

DT1[.(DT2$group), .(popular = .N >= 2L), by = .EACHI]

Когда вы присоединяетесь к одному столбцу символа, вы можете полностью исключить синтаксис .()/J() (для удобства). Таким образом, это можно также записать как:

DT1[DT2$group, .(popular = .N >= 2L), by = .EACHI]

Ответ 2

Вот как бы я это сделал: сначала подсчитайте количество раз, когда каждая группа появляется в DT1, а затем просто присоединяйте DT2 и DT1.

require(data.table)
DT1 <- data.table(num = 1:6, group = c("A", "B", "B", "B", "A", "C"))
DT2 <- data.table(group = c("A", "B", "C"))

#solution:
DT1[,num_counts:=.N,by=group] #the number of entries in this group, just count the other column
setkey(DT1, group)
setkey(DT2, group)
DT2 = DT1[DT2,mult="last"][,list(group, popular = (num_counts >= 2))]

#> DT2
#   group popular
#1:     A    TRUE
#2:     B    TRUE
#3:     C   FALSE