2017-08-21 4 views
0

Étant donné un vecteur de valeurs binaires out_2 le code ci-dessous renvoie un vecteur de même longueur que out_2 appelé out_1. Les entrées de out_1 comptent le nombre d'éléments similaires successifs dans out_2 avant le prochain changement de signe. Si vous imprimez la dernière cbind() je pense que vous verrez ce que je veux dire.Incrémentation des valeurs vectorielles sous condition (redémarrage conditionnel de la somme cumulée) - Version vectorisée?

library(zoo) 
    n = 10 
    out_2 = rep(NA, n) 
    out_2[sample.int(n, 3)] = sample(c(-1, 1), 3, replace = TRUE) 
    out_2 = zoo::na.locf(out_2) 
    out_1 = out_2 
    out_1[length(out_2)] = 1 
    for(i in (length(out_2) - 1):1){ 
    out_1[i] = ifelse(out_2[i + 1] == out_2[i], out_1[i + 1] + 1, 1) 
    } 
cbind(out_1, out_2) 

Je me demandais s'il y a un moyen vectorisé d'une doublure pour obtenir out_1 de out_2 (à savoir la vectorisation explicite de boucle)?

Répondre

3

J'utiliser rle de la base R. La partie la plus délicate est d'obtenir l'ordre inverse pour le vecteur out_1, il doit passer par `lapply »

out_1<- unlist(lapply(rle(out_2)$lengths, function(x) seq(x, by=-1))) 

Et le résultat est (?):

cbind(out_1, out_2) 
     out_1 out_2 
[1,]  2 -1 
[2,]  1 -1 
[3,]  1  1 
[4,]  6 -1 
[5,]  5 -1 
[6,]  4 -1 
[7,]  3 -1 
[8,]  2 -1 
[9,]  1 -1 

Si vous êtes flexible avec la sortie et vous n'avez pas besoin d'être dans l'ordre inverse, vous pouvez simplement utiliser la fonction sequence.

out_1<- sequence(rle(out_2)$lengths) 
cbind(out_1, out_2) 
     out_1 out_2 
[1,]  1 -1 
[2,]  2 -1 
[3,]  1  1 
[4,]  1 -1 
[5,]  2 -1 
[6,]  3 -1 
[7,]  4 -1 
[8,]  5 -1 
[9,]  6 -1 
1

Cette solution effectue une itération sur les valeurs consécutives groupées (pas sur out_2 comme dans votre exemple). Fondamentalement, nous regroupons les valeurs consécutives, vérifions la taille de ce groupe et créons le vecteur N:1.

foo <- rle(out_2) 
cbind(unlist(sapply(foo$lengths, function(x) x:1)), 
     rep(foo$values, foo$lengths))