Il ne semble y avoir aucune fonction qui calcule simplement la moyenne mobile sur numpy / scipy, conduisant à des solutions alambiquées .
Ma question est double:
python
numpy
scipy
time-series
moving-average
Goncalopp
la source
la source
Réponses:
Si vous voulez juste une moyenne, vous pouvez facilement non pondérée simple mouvement de mettre en œuvre avec
np.cumsum
, ce quipeut êtreest des méthodes basées plus rapide que FFT:EDIT Correction d'une mauvaise indexation ponctuelle repérée par Bean dans le code. ÉDITER
Donc, je suppose que la réponse est: c'est vraiment facile à mettre en œuvre, et peut-être que numpy est déjà un peu gonflé de fonctionnalités spécialisées.
la source
ret[n:] -= ret[:-n]
n'est pas le même queret[n:] = ret[n:] - ret[:-n]
. J'ai corrigé le code dans cette réponse. Edit: Non, quelqu'un d'autre vient de me battre.L'absence de fonction spécifique à un domaine par NumPy est peut-être due à la discipline de l'équipe principale et à la fidélité à la directive principale de NumPy: fournir un type de tableau à N dimensions , ainsi que des fonctions pour créer et indexer ces tableaux. Comme de nombreux objectifs fondamentaux, celui-ci n'est pas petit et NumPy le fait avec brio.
Le SciPy (beaucoup) plus grand contient une collection beaucoup plus grande de bibliothèques spécifiques à un domaine (appelées sous- packages par les développeurs de SciPy) - par exemple, l'optimisation numérique ( optimiser ), le traitement du signal ( signal ) et le calcul intégral ( intégrer ).
Je suppose que la fonction que vous recherchez se trouve dans au moins l'un des sous-packages SciPy ( scipy.signal peut-être); Cependant, je chercherais d'abord dans la collection de scikits SciPy , identifierais le (s) scikit (s) pertinent (s) et chercherais la fonction qui l'intéresse.
Les scikits sont des packages développés indépendamment basés sur NumPy / SciPy et dirigés vers une discipline technique particulière (par exemple, scikits-image , scikits-learn , etc.) Plusieurs d'entre eux étaient (en particulier, l'impressionnant OpenOpt pour l'optimisation numérique) étaient très appréciés, projets mûrs bien avant de choisir de résider sous la rubrique relativement nouvelle des scikits . La page d'accueil de Scikits comme ci-dessus répertorie environ 30 de ces scikits , bien qu'au moins plusieurs d'entre eux ne soient plus en développement actif.
Suivre ce conseil vous conduirait à des scikits-timeseries ; cependant, ce paquet n'est plus en cours de développement actif; En effet, Pandas est devenu, AFAIK, la bibliothèque de séries chronologiques de facto basée sur NumPy .
Pandas a plusieurs fonctions qui peuvent être utilisées pour calculer une moyenne mobile ; le plus simple d'entre eux est probablement rolling_mean , que vous utilisez comme ceci:
Maintenant, appelez simplement la fonction rolling_mean en passant l'objet Series et une taille de fenêtre , qui dans mon exemple ci-dessous est de 10 jours .
vérifier que cela a fonctionné - par exemple, comparez les valeurs de 10 à 15 dans la série d'origine par rapport à la nouvelle série lissée avec une moyenne de roulement
La fonction rolling_mean, ainsi qu'une douzaine d'autres fonctions sont regroupées de manière informelle dans la documentation Pandas sous la rubrique Fonctions de la fenêtre mobile ; un deuxième groupe de fonctions apparentées dans Pandas est appelé fonctions à pondération exponentielle (par exemple, ewma , qui calcule une moyenne pondérée en mouvement exponentiel). Le fait que ce deuxième groupe ne soit pas inclus dans le premier ( fonctions de fenêtre mobile ) est peut-être dû au fait que les transformations à pondération exponentielle ne reposent pas sur une fenêtre de longueur fixe
la source
Un moyen simple d'y parvenir est d'utiliser
np.convolve
. L'idée derrière cela est d'exploiter la façon dont la convolution discrète est calculée et de l'utiliser pour renvoyer une moyenne mobile . Cela peut être fait en convoluant avec une séquence denp.ones
une longueur égale à la longueur de la fenêtre glissante que nous voulons.Pour ce faire, nous pourrions définir la fonction suivante:
Cette fonction prendra la convolution de la séquence
x
et une séquence de uns de longueurw
. Notez que le choixmode
estvalid
tel que le produit de convolution n'est donné que pour les points où les séquences se chevauchent complètement.Quelques exemples:
Pour une moyenne mobile avec une fenêtre de longueur,
2
nous aurions:Et pour une fenêtre de longueur
4
:Comment ça
convolve
marche?Regardons plus en profondeur la façon dont la convolution discrète est calculée. La fonction suivante vise à reproduire la méthode de
np.convolve
calcul des valeurs de sortie:Ce qui, pour le même exemple ci-dessus, donnerait également:
Donc ce qui est fait à chaque étape est de prendre le produit interne entre le tableau de uns et la fenêtre courante . Dans ce cas, la multiplication par
np.ones(w)
est superflue étant donné que nous prenons directement lesum
de la séquence.Ci-dessous est un exemple de la façon dont les premières sorties sont calculées pour que ce soit un peu plus clair. Supposons que nous voulons une fenêtre de
w=4
:Et la sortie suivante serait calculée comme:
Et ainsi de suite, renvoyer une moyenne mobile de la séquence une fois que tous les chevauchements ont été effectués.
la source
mode='valid'
peut être remplacé par'same'
. Juste dans ce cas, les points de bord graviteront vers zéro.Voici une variété de façons de le faire, ainsi que quelques repères. Les meilleures méthodes sont les versions utilisant du code optimisé d'autres bibliothèques. La
bottleneck.move_mean
méthode est probablement la meilleure partout. L'scipy.convolve
approche est également très rapide, extensible et syntaxiquement et conceptuellement simple, mais ne s'adapte pas bien aux très grandes valeurs de fenêtre. Lanumpy.cumsum
méthode est bonne si vous avez besoin d'unenumpy
approche pure .Remarque: certains d'entre eux (par exemple
bottleneck.move_mean
) ne sont pas centrés et déplaceront vos données.Calendrier, petite fenêtre (n = 3)
Calendrier, grande fenêtre (n = 1001)
Mémoire, petite fenêtre (n = 3)
Mémoire, grande fenêtre (n = 1001)
la source
Cette réponse utilisant Pandas est adaptée d'en haut, car elle
rolling_mean
ne fait plus partie de PandasMaintenant, appelez simplement la fonction
rolling
sur le dataframe avec une taille de fenêtre, qui dans mon exemple ci-dessous est de 10 jours.la source
Je pense que cela peut être facilement résolu en utilisant un goulot d'étranglement
Voir l'exemple de base ci-dessous:
Cela donne une moyenne de déplacement le long de chaque axe.
"mm" est la moyenne mobile de "a".
"window" est le nombre maximum d'entrées à considérer pour la moyenne mobile.
"min_count" est le nombre minimal d'entrées à considérer pour la moyenne mobile (par exemple pour le premier élément ou si le tableau a des valeurs nan).
La bonne partie est que Bottleneck aide à gérer les valeurs nanométriques et il est également très efficace.
la source
Dans le cas où vous voulez prendre soin des conditions de bord avec soin ( calculer la moyenne uniquement à partir des éléments disponibles sur les bords ), la fonction suivante fera l'affaire.
la source
Essayez ce morceau de code. Je pense que c'est plus simple et fait le travail. lookback est la fenêtre de la moyenne mobile.
Dans le
Data[i-lookback:i, 0].sum()
J'ai mis0
pour faire référence à la première colonne de l'ensemble de données, mais vous pouvez mettre n'importe quelle colonne que vous aimez au cas où vous auriez plus d'une colonne.la source
Je voulais en fait un comportement légèrement différent de la réponse acceptée. Je construisais un extracteur de caractéristiques de moyenne mobile pour un
sklearn
pipeline, j'ai donc exigé que la sortie de la moyenne mobile ait la même dimension que l'entrée. Ce que je veux, c'est que la moyenne mobile suppose que la série reste constante, c'est-à-dire qu'une moyenne mobile de[1,2,3,4,5]
avec la fenêtre 2 donnerait[1.5,2.5,3.5,4.5,5.0]
.Pour les vecteurs de colonne (mon cas d'utilisation), nous obtenons
Et pour les tableaux
Bien sûr, il n'est pas nécessaire de supposer des valeurs constantes pour le remplissage, mais cela devrait être adéquat dans la plupart des cas.
la source
talib contient un outil de moyenne mobile simple, ainsi que d'autres outils de calcul de moyenne similaires (c.-à-d. moyenne mobile exponentielle). Ci-dessous compare la méthode à certaines des autres solutions.
Une mise en garde est que le réel doit avoir des éléments de
dtype = float
. Sinon, l'erreur suivante est généréela source
Voici une implémentation rapide utilisant numba (attention aux types). Notez qu'il contient des nans lorsqu'ils sont décalés.
la source
la source
J'utilise soit la solution de la réponse acceptée , légèrement modifiée pour avoir la même longueur pour la sortie que l'entrée, soit
pandas
la version comme mentionné dans un commentaire d'une autre réponse. Je résume les deux ici avec un exemple reproductible pour référence future:la source
En comparant la solution ci-dessous avec celle qui utilise du sperme de numpy, celle-ci prend presque la moitié du temps . En effet, il n'est pas nécessaire de parcourir tout le tableau pour faire le sperme, puis de faire toute la soustraction. De plus, le sperme peut être " dangereux " si le tableau est énorme et le nombre est énorme ( débordement possible ). Bien sûr, ici aussi le danger existe, mais au moins ne sont additionnés que les nombres essentiels.
la source