Je viens de tomber sur ça aujourd'hui en regardant une question sur 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]
Pour moi, la première façon semble idiomatique, étant donné que la variable doit finir par users
à la fin.
Un autre : https://stackoverflow.com/a/47338118/ (gtail)
Un autre https://stackoverflow.com/a/51569126/ devrait faire DT[, mx := max(pt), by=Subject][, diff := mx - pt][]
je suppose
Un autre, particulièrement intéressé par les performances de la mémoire : https://stackoverflow.com/q/52189712 " data.table reference semantics: memory usage of iterating through all column "
Un autre veut scale
/deean plusieurs variables : https://stackoverflow.com/q/52528123
Une autre prise max par groupe avec une condition de sous-ensemble et ajout avec := (voir la réponse d'akrun) https://stackoverflow.com/a/54911855/ également liée à la partie déjà terminée de #971
Je voulais juste souligner que l'activation de cela peut permettre d'utiliser efficacement GForce pour des expressions complexes, bien qu'avec un peu de travail. Par exemple, je montre dans cet article comment l'activer pour :
slope <- function(x, y) {
x_ux <- x - mean(x)
uy <- mean(y)
sum(x_ux * (y - uy)) / sum(x_ux ^ 2)
}
En faisant:
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)]
Alors que si GForce était supporté dans :=
nous pourrions faire :
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)]
Ce qui a l'air plus propre et devrait être plus rapide.
Les discussions avec @MichaelChirico m'ont fait réaliser qu'un cousin très proche de ce problème est :
> 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
Lien croisé vers #523.
Commentaire le plus utile
Je voulais juste souligner que l'activation de cela peut permettre d'utiliser efficacement GForce pour des expressions complexes, bien qu'avec un peu de travail. Par exemple, je montre dans cet article comment l'activer pour :
En faisant:
Alors que si GForce était supporté dans
:=
nous pourrions faire :Ce qui a l'air plus propre et devrait être plus rapide.