Me encontré con esto hoy mirando una pregunta sobre SO :
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))
users = actions[, other_var := 1, by=User_id]
# verbose says: the following is not optimized
users[, value_one := 0 ]
users[actions[category==1], value_one := sum(value), on="User_id", by=.EACHI, verbose=TRUE]
# verbose says: the following is optimized
rbind(
actions[category==1],
unique(actions[,"User_id", with=FALSE])[, value := 0 ],
fill=TRUE)[, sum(value), by=User_id, verbose=TRUE]
Para mí, la primera forma parece idiomática, considerando que la variable debe terminar en users
al final.
Otro: https://stackoverflow.com/a/47338118/ (gtail)
Otro https://stackoverflow.com/a/51569126/ debería hacer DT[, mx := max(pt), by=Subject][, diff := mx - pt][]
supongo
Otro, específicamente interesado en el rendimiento de la memoria: https://stackoverflow.com/q/52189712 "semántica de referencia de data.table: uso de memoria de iterar a través de todas las columnas"
Otro, quiere scale
/ degradar múltiples variables: https://stackoverflow.com/q/52528123
Otro tomando el máximo por grupo con una condición de subconjunto y agregando con: = (ver la respuesta de akrun) https://stackoverflow.com/a/54911855/ también está relacionado con la parte ya completada de # 971
Solo quería enfatizar que habilitar esto puede permitir usar GForce de manera efectiva para expresiones complejas, aunque con algo de trabajo. Por ejemplo, muestro en esta publicación cómo habilitarlo para:
slope <- function(x, y) {
x_ux <- x - mean(x)
uy <- mean(y)
sum(x_ux * (y - uy)) / sum(x_ux ^ 2)
}
Haciendo:
DT <- data.table(grp, x, y)
setkey(DT, grp)
DTsum <- DT[, .(ux=mean(x), uy=mean(y)), keyby=grp]
DT[DTsum, `:=`(x_ux=x - ux, y_uy=y - uy)]
DT[, `:=`(x_ux.y_uy=x_ux * y_uy, x_ux2=x_ux^2)]
DTsum <- DT[, .(x_ux.y_uy=sum(x_ux.y_uy), x_ux2=sum(x_ux2)), keyby=grp]
res.slope.dt2 <- DTsum[, .(grp, V1=x_ux.y_uy / x_ux2)]
Mientras que si GForce fuera compatible con :=
, podríamos hacer:
DT <- data.table(grp, x, y)
DT[, `:=`(ux=mean(x), uy=mean(y)), keyby=grp]
DT[, `:=`(x_ux=x - ux, y_uy=y - uy)]
DT[, `:=`(x_ux.y_uy=x_ux * y_uy, x_ux2=x_ux^2)]
DTsum <- DT[, .(x_ux.y_uy=sum(x_ux.y_uy), x_ux2=sum(x_ux2)), keyby=grp]
res.slope.dt3 <- DTsum[, .(grp, x_ux.y_uy/x_ux2)]
Que parece más limpio y debería ser más rápido.
Las conversaciones con @MichaelChirico me hacen darme cuenta de que un primo muy cercano a este problema es:
> DT <- data.table(x, y, grp)
> DT[, .(x, mean(x)), keyby=grp]
Detected that j uses these columns: x
Finding groups using forderv ... 1.049s elapsed (0.946s cpu)
Finding group sizes from the positions (can be avoided to save RAM) ... 0.011s elapsed (0.011s cpu)
lapply optimization is on, j unchanged as 'list(x, mean(x))'
GForce is on, left j unchanged
Old mean optimization changed j from 'list(x, mean(x))' to 'list(x, .External(Cfastmean, x, FALSE))'
Making each group and running j (GForce FALSE) ...
collecting discontiguous groups took 1.293s for 999953 groups
eval(j) took 1.860s for 999953 calls
5.517s elapsed (3.862s cpu)
grp x V2
1: 1 0.2151365 0.5512966
2: 1 0.5358256 0.5512966
3: 1 0.8496598 0.5512966
4: 1 0.8480730 0.5512966
5: 1 0.3464458 0.5512966
---
9999996: 1000000 0.2601940 0.5474986
9999997: 1000000 0.7940921 0.5474986
9999998: 1000000 0.3825493 0.5474986
9999999: 1000000 0.1786861 0.5474986
10000000: 1000000 0.9179119 0.5474986
Enlace cruzado a # 523.
Comentario más útil
Solo quería enfatizar que habilitar esto puede permitir usar GForce de manera efectiva para expresiones complejas, aunque con algo de trabajo. Por ejemplo, muestro en esta publicación cómo habilitarlo para:
Haciendo:
Mientras que si GForce fuera compatible con
:=
, podríamos hacer:Que parece más limpio y debería ser más rápido.