R data.table - частично агрегировать внутри группы и выполнить операцию

Есть ли хороший способ создать подгруппу в столбце группировки в операциях data.table?

Результат, который я хотел бы, - это вывод из этого:

dt <- data.table(
  group = c("a","a","a","b","b","b","c","c"),
  value = c(1,2,3,4,5,6,7,8)
)

dt[group!="a", group:="Other"][, sum(value), by=.(group)][]

который дает

group V1
a     6
Other 30

Однако это изменяет исходный data.table. Я не знаю, есть ли другой способ сделать это, который не включал бы слияние двух data.table. Я могу представить себе более сложный вариант использования, когда я хочу group %in% c("a","b") в качестве одной подгруппы и group %in% c("c","d") в другой и т. д.


person moman822    schedule 26.09.2018    source источник
comment
Что касается более сложного варианта использования, просто поместите сопоставление в отдельную таблицу и выполните соединение: mDT = data.table(g = c(1,1,2,2), group=letters[1:4]); dt[, sum(value), by=mDT[dt, on=.(group), x.g]]   -  person Frank    schedule 27.09.2018


Ответы (1)


Я думаю, что это похоже на право SQL, исключающее присоединение (используя терминологию здесь)

Можно пройти по группам и внутри каждой группы выполнить антиприсоединение

#group no longer found in .SD, hence make a copy of the column
dt[, g:=group]

#go through each group, anti-join with other groups, aggregate value
dt[, .(
        sumGrpVal=sum(value), 
        sumNonGrpVal=dt[!.SD, sum(value), on=c("group"="g")]
    ), by=.(group)]

или еще более быстрый способ:

dt[, .(
    sumGrpVal=sum(value), 
    sumNonGrpVal=dt[group!=.BY$group, sum(value)]
), by=.(group)]

выход:

   group sumGrpVal sumNonGrpVal
1:     a         6           30
2:     b        15           21
3:     c        15           21
person chinsoon12    schedule 27.09.2018