2016-05-18 11 views
10

Ho il seguente problema, che probabilmente ha una soluzione molto semplice: Quando usodata.table DOVE PRIMA di

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] 

Il problema è, che a quanto pare primi ordina fuori le righe in cui categoria è 1 e quindi usa il comando by. Quindi quello che ottengo è:

User_id V1 
1: Carl 30 
2:  Moe 50 

Ma quello che voglio è:

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

Sto costruendo un data.table informazioni solo contenente circa gli utenti, quindi:

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

che genera errori o include valori errati, quando ci sono utenti che non hanno voce.

+0

si potrebbe usare 'azioni [, sum (IfElse (categoria == 1, valore, 0)), per = User_id] '. – nrussell

+0

IIUC relativo a [FR # 788] (https://github.com/Rdatatable/data.table/issues/788) – MichaelChirico

risposta

11

Questo è quasi succinto, e ha il compito.

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 

Se la relativa inefficienza di cui sopra è un problema nel vostro caso d'uso, ecco un'alternativa più efficiente:

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 
+3

O semplicemente "actions [, sum (value [category == 1]), by = User_id] 'senza scherzare con' .SD'. Sebbene, sebbene questi approcci appaiano "* quasi come succinti *", sono molto meno efficienti di quanto OP stava cercando di fare perché si filtra per 'category == 1' * di ogni *' User_id' piuttosto che una sola volta. –

+0

@DavidArenburg Concordato. Avevo dubbi simili, quindi ho appena aggiunto una seconda opzione, meno succinta ma più efficiente. –

+0

Un altro modo per gestire i livelli inutilizzati sarebbe una fusione come 'actions [category == 1] [users, sum (value, na.rm = TRUE), on =" User_id ", di = .EACHI]'. Sfortunatamente, sembra che 'sum' non attivi l'ottimizzazione di GForce se na.rm è implicato – Frank

Problemi correlati