2015-01-15 3 views
7

Я сталкивался с (я думаю), это сложная проблема с скоплениями на data.table Я следующий data.tableR data.table условное объединение

structure(list(id1 = c("a", "a", "a", "b", "b", "c", "c"), id2 = c("x", 
"y", "z", "x", "u", "y", "z"), val = c(2, 1, 2, 1, 3, 4, 3)), .Names = c("id1", 
"id2", "val"), row.names = c(NA, -7L), class = c("data.table", 
"data.frame"), .internal.selfref = <pointer: 0x1f66a78>) 

Я хотел бы создать условные агрегаты на val column для этих данных на основе второй колонки id2. Способ агрегации состоит только в том, чтобы включать только группы id1, которые имеют по меньшей мере один элемент из заданного элемента id2. Я приведу пример, чтобы показать, что я имею в виду.

Условный агрегат для x (первая строка второго столбца) будет включать в себя val значения 2,1,2 для id1 = a и val значения = 1,3 от id1 = b, потому что id2=x существует для них, но никаких значений из id1=c, в результате чего значение 2 + 1 + 2 + 1 + 3 = 9. Я хочу, чтобы 9 был 4-м столбцом в каждой строке, где появляется id2 = x.

Аналогичным образом, я хочу сделать это для всех значений id2. Таким образом, конечный результат будет

id1 id2 val c.sum 
1: a x 2  9 
2: a y 1 12 
3: a z 2 12 
4: b x 1  9 
5: b u 3  4 
6: c y 4 12 
7: c z 3 14 

Возможно ли это в R, data.table? Или любой другой пакет/метод? Заранее спасибо

+2

Я путать с ожидаемым результатом. Если id2 содержит z, вы ожидаете 12 в c.cum. Я что-то упускаю? – jazzurro

+0

Опечатка, я имел в виду 12. – broccoli

+0

Это все хорошо. Теперь у вас есть ответы. :) – jazzurro

ответ

3

Учитывая, что d является вашей входной структурой:

library(data.table) 

d[,c.sum:=sum(d$val[d$id1 %in% id1]),by=id2][] 

Как это работает: by=id2 группы ввод таблица d данных по id2; d$id1 %in% id1 выбирает строки в d, чьи id1 соответствует id1 группы, находящейся на рассмотрении; sum(d$val[...]) берет сумму значений из таких строк; наконец, c.sum:=sum(...) добавляет столбец c.sum в d. Окончание [] необходимо только для целей печати.

Выход:

# id1 id2 val c.sum 
# 1: a x 2  9 
# 2: a y 1 12 
# 3: a z 2 12 
# 4: b x 1  9 
# 5: b u 3  4 
# 6: c y 4 12 
# 7: c z 3 12 
+0

Я получаю все значения 16. –

+0

@BondedDust: может ли это быть связано с версией 'data.table'? Я использую data.table_1.9.4. –

+0

Для этого необходимо загрузить пакет. Я загрузил 'data.table', но указанная выше строка не работает для меня. можете ли вы добавить любые операторы 'library()', которые необходимы для запуска этого решения? – Jthorpe

2

Это немного перебор, но он должен работать (при условии, data в структуру данных):

id1_sums <- tapply(data$val,data$id1,sum) 
for(id in unique(data$id2)) 
    data$c.sum[data$id2 == id] <- sum(
      id1_sums[which(names(id1_sums) %in% data$id1[data$id2 == id])]) 
Смежные вопросы