daroczig écrit "vous pouvez écrire un code plus propre lot basé sur diff
" ...
est ici une façon:
split(v, cumsum(diff(c(-Inf, v)) != 1))
EDIT (timings ajoutés):
Tommy a découvert cela pourrait être plus rapide en faisant attention aux types; la raison pour laquelle il est devenu plus rapide est que split
est plus rapide sur les entiers, et est encore plus rapide sur les facteurs.
Voici la solution de Joshua; le résultat du cumsum
est un numérique car il est c
'd avec 1
, donc c'est le plus lent.
system.time({
a <- cumsum(c(1, diff(v) != 1))
split(v, a)
})
# user system elapsed
# 1.839 0.004 1.848
Juste c
ing avec 1L
de sorte que le résultat est un nombre entier accélère considérablement vers le haut.
system.time({
a <- cumsum(c(1L, diff(v) != 1))
split(v, a)
})
# user system elapsed
# 0.744 0.000 0.746
Ceci est la solution de Tommy, pour référence; c'est aussi se dédoubler sur un nombre entier.
> system.time({
a <- cumsum(c(TRUE, diff(v) != 1L))
split(v, a)
})
# user system elapsed
# 0.742 0.000 0.746
Voici ma solution originale; il est également divisé sur un nombre entier.
system.time({
a <- cumsum(diff(c(-Inf, v)) != 1)
split(v, a)
})
# user system elapsed
# 0.750 0.000 0.754
est ici Joshua, avec le résultat converti en un nombre entier avant la split
.
system.time({
a <- cumsum(c(1, diff(v) != 1))
a <- as.integer(a)
split(v, a)
})
# user system elapsed
# 0.736 0.002 0.740
Toutes les versions split
sur un vecteur entier sont à peu près les mêmes; cela pourrait être encore plus rapide si ce vecteur entier était déjà un facteur, car la conversion d'entier en facteur prend environ la moitié du temps. Ici, je le fais en un facteur directement; ceci n'est pas recommandé en général car cela dépend de la structure de la classe de facteurs. C'est fait ici à des fins de comparaison seulement.
system.time({
a <- cumsum(c(1L, diff(v) != 1))
a <- structure(a, class = "factor", levels = 1L:a[length(a)])
split(v,a)
})
# user system elapsed
# 0.356 0.000 0.357
oui, c'est beaucoup plus propre! :) Je ne connaissais pas 'split', merci d'avoir attiré mon attention sur cette fonction utile. – daroczig
Je devrais noter que l'on devrait faire attention en utilisant 'as.integer' car il retourne la valeur tronquée, ce qui peut ne pas être ce que vous voulez quand le numérique a été créé avec l'arithmétique en virgule flottante, par exemple,' as.integer (0.3 * 3 + 0.1) 'renvoie' 0'. – Aaron