Подтвердить что ты не робот

Data.table WHERE before BY

У меня есть следующая проблема, которая, вероятно, довольно простое решение: Когда я использую

library (data.table)
actions = data.table(User_id = c("Carl","Carl","Carl","Lisa","Moe"),
                     category = c(1,1,2,2,1),
                     value= c(10,20,30,40,50))

   User_id category value
1:    Carl        1    10
2:    Carl        1    20
3:    Carl        2    30
4:    Lisa        2    40
5:     Moe        1    50

actions[category==1,sum(value),by= User_id]

Проблема заключается в том, что, по-видимому, она сначала сортирует строки, где категория равна 1, а затем использует команду by. Так что я получаю:

   User_id V1
1:    Carl 30
2:     Moe 50

Но я хочу:

   User_id V1
1:    Carl 30
2:    Lisa 0
3:     Moe 50

Я создаю таблицу данных, содержащую только информацию о пользователях, поэтому:

users = actions[,User_id,by= User_id]
users$value_one = actions[category==1,.(value_one =sum(value)),by= User_id]$value_one

который выдает ошибки или включает неправильные значения, когда есть некоторые пользователи, у которых нет записи.

4b9b3361

Ответ 1

Это почти так же лаконично и выполняется.

actions[, .SD[category==1, sum(value)], by=User_id]
#    User_id V1
# 1:    Carl 30
# 2:    Lisa  0
# 3:     Moe 50

## Or, better yet, no need to muck around with .SD, (h.t. David Arenburg)
actions[, sum(value[category == 1]), by = User_id]
#    User_id V1
# 1:    Carl 30
# 2:    Lisa  0
# 3:     Moe 50

Если относительная неэффективность вышеизложенного является проблемой в вашем случае использования, здесь более эффективная альтернатива:

res <- actions[, .(val=0), by=User_id]
res[actions[category==1, .(val=sum(value)), by=User_id], val:=i.val, on="User_id"]    
res
#    User_id val
# 1:    Carl  30
# 2:    Lisa   0
# 3:     Moe  50