12
votes

Comment puis-je prendre un produit roulant à l'aide de données.Table

      x Prod.3
1: 1.00 0.7200
2: 0.90 0.5400
3: 0.80 0.3000
4: 0.75 0.0375
5: 0.50     NA
6: 0.10     NA

0 commentaires

4 Réponses :


10
votes

Vous pouvez essayer xxx

correspondant à la sortie attendue xxx


1 commentaires

C'est lent (comme indiqué par Arun), mais c'est simple et assez rapide pour mon étui d'utilisation.



15
votes

Voici de deux manières .. bien que non les implémentations les plus efficaces possible: xxx pré>


un autre à l'aide de incorporé () code>: p> XXX PRE>


Benchmarks: P>

set.seed(1L)
dt = data.table(x=runif(1e6))
zoo_fun <- function(dt, N) {
    rollapply(dt$x, N, FUN=prod, fill=NA, align='left')
}

dt1_fun <- function(dt, N) {
    dt[, prod := prod(dt$x[.I:(.I+N-1L)]), by=1:nrow(dt)]
    dt$prod
}

dt2_fun <- function(dt, N) {
    tmp = apply(embed(dt$x, N), 1L, prod)
    tmp[1:nrow(dt)]
}

david_fun <- function(dt, N) {
    Reduce(`*`, shift(dt$x, 0:(N-1L), type="lead"))
}

system.time(ans1 <- zoo_fun(dt, 3L))
#    user  system elapsed 
#   8.879   0.264   9.221 
system.time(ans2 <- dt1_fun(dt, 3L))
#    user  system elapsed 
#  10.660   0.133  10.959
system.time(ans3 <- dt2_fun(dt, 3L))
#    user  system elapsed 
#   1.725   0.058   1.819 
system.time(ans4 <- david_fun(dt, 3L))
#    user  system elapsed 
#   0.009   0.002   0.011 

all.equal(ans1, ans2) # [1] TRUE
all.equal(ans1, ans3) # [1] TRUE
all.equal(ans1, ans4) # [1] TRUE


2 commentaires

Dans ce code, une seule colonne est utilisée. Comment fonctionne-t-il un certain nombre de colonnes la voie SDCols? dt [ prod: = prod (dolld $ x [.Je :(. i + n-1l)]), par = 1: nrow (dt)].


@Arun Il est vraiment étonnant de voir combien peut être réalisé dans les données.Table [.] en manipulant .n , .i et . SD . N'aurait pas besoin de se rappeler beaucoup d'autres fonctions!



15
votes

Voici une autre version possible à l'aide de data.table :: shift combiné avec Réduire (selon @aruns Commentaire) xxx < Code> Shift est vectorisé, ce qui signifie qu'il peut créer plusieurs nouvelles colonnes à une fois en fonction du vecteur transmis à l'argument n . Ensuite, Réduire s'applique fondamentalement * à tous les vecteurs à une fois d'élément-sage.


4 commentaires

C'est cool .. vous pouvez faire: réduire (`*`, décalage (dt, 0: 2, type = "plomb"))


Incroyable accélère! Est-il possible de le faire fonctionner sur la variable n ? Ensuite, je pourrais l'appliquer à ce sujet: Stackoverflow.com/q/21368245/2490497


@jan je ne suis pas devant un ordinateur en ce moment, alors jetez un coup d'oeil demain. Je ne sais pas non plus ce que vous entendez par "variable n".


@Davidarenburg Faire le vecteur de la fenêtre roulante au lieu de scalaire donne un moyen de coder les moyennes mobiles adaptatives.



1
votes

maintenant data.table a des fonctions de roulement rapides. Donc, @Mamoun Benghezal L'approche peut être utilisée comme xxx

ceci est très rapide, mais pas aussi vite que la fonction de @David Arenburg. Utilisation de la référence de @arun: xxx


0 commentaires