Cet article est la suite d'un autre article lié à une méthode générique de détection des valeurs aberrantes dans les séries chronologiques . Fondamentalement, à ce stade, je suis intéressé par un moyen robuste de découvrir la périodicité / saisonnalité d’une série temporelle générique affectée par beaucoup de bruit. Du point de vue du développeur, j'aimerais une interface simple telle que:
unsigned int discover_period(vector<double> v);
Où v
est le tableau contenant les échantillons et la valeur de retour est la période du signal. Le point principal est que, encore une fois, je ne peux faire aucune hypothèse concernant le signal analysé. J'ai déjà essayé une approche basée sur l'autocorrélation du signal (détection des pics d'un corrélogramme), mais ce n'est pas robuste comme je le voudrais.
la source
Réponses:
Si vous ne savez vraiment pas quelle est la périodicité, la meilleure approche consiste probablement à trouver la fréquence correspondant au maximum de la densité spectrale. Cependant, le spectre aux basses fréquences sera affecté par la tendance, vous devez donc commencer par décourager la série. La fonction R suivante devrait faire le travail pour la plupart des séries. Il est loin d'être parfait, mais je l'ai testé sur quelques dizaines d'exemples et cela semble fonctionner correctement. Il renverra 1 pour les données qui n'ont pas de périodicité forte, et la durée de la période sinon.
Mise à jour: version 2 de la fonction. C'est beaucoup plus rapide et semble être plus robuste.
la source
findfrequency
Si vous vous attendez à ce que le processus soit stationnaire (la périodicité / la saisonnalité ne changera pas avec le temps), un périodogramme ressemblant au chi carré (voir par exemple Sokolove et Bushell, 1978) peut constituer un bon choix. Il est couramment utilisé dans l'analyse de données circadiennes qui peuvent contenir des quantités de bruit extrêmement importantes, mais dont les périodicités sont très stables.
Cette approche ne fait aucune hypothèse sur la forme de la forme d'onde (sauf si elle est cohérente d'un cycle à l'autre), mais exige que tout bruit soit de moyenne constante et non corrélé au signal.
Les deux dernières lignes ne sont qu'un exemple, montrant qu'il peut identifier la période d'une fonction trigonométrique pure, même avec beaucoup de bruit additif.
Comme écrit, le dernier argument (
alpha
) de l'appel est superflu, la fonction renvoie simplement la "meilleure" période qu'il peut trouver; décommentez la premièrereturn
déclaration et commentez la seconde pour qu'elle renvoie une liste de toutes les périodes significatives au niveaualpha
.Cette fonction ne fait aucune sorte de vérification de cohérence pour vous assurer que vous avez mis des périodes identifiables, elle ne fonctionne pas (avec des périodes fractionnaires), et il n’existe aucune sorte de contrôle de comparaison multiple intégré si vous décidez de le faire. regarde plusieurs périodes. Mais à part cela, il devrait être raisonnablement robuste.
la source
Vous voudrez peut-être définir plus clairement ce que vous voulez (pour vous-même, sinon ici). Si ce que vous recherchez est la période stationnaire la plus statistiquement significative contenue dans vos données bruitées, il existe essentiellement deux itinéraires à suivre:
1) calculer une estimation robuste d'autocorrélation et prendre le coefficient maximal
2) calculer une estimation robuste de densité spectrale de puissance et utiliser le maximum du spectre
Le problème avec # 2 est que pour toute série chronologique bruyante, vous obtiendrez une grande quantité de puissance dans les basses fréquences, ce qui rend difficile la distinction. Il existe certaines techniques pour résoudre ce problème (c'est-à-dire pré-blanchir, puis estimer le PSD), mais si la période réelle de vos données est suffisamment longue, la détection automatique sera difficile.
Votre meilleur choix est probablement de mettre en œuvre une routine d'autocorrélation robuste, comme celle décrite au chapitre 8.6, 8.7 dans Statistiques robustes - Théorie et méthodes de Maronna, Martin et Yohai. La recherche sur Google pour "robust durbin-levinson" donnera également des résultats.
Si vous cherchez simplement une réponse simple, je ne suis pas sûre qu'il en existe une. La détection de période dans une série chronologique peut être compliquée, et demander une routine automatisée capable d'effectuer de la magie peut s'avérer excessif.
la source
Vous pouvez utiliser la théorie de la transformation de Hilbert à partir de DSP pour mesurer la fréquence instantanée de vos données. Le site http://ta-lib.org/ contient un code source ouvert permettant de mesurer la période de cycle dominante des données financières; la fonction correspondante est appelée HT_DCPERIOD; vous pourrez peut-être l'utiliser ou adapter le code à vos besoins.
la source
Une approche différente pourrait être la décomposition en mode empirique. Le package R est appelé EMD développé par l'inventeur de la méthode:
La méthode a été baptisée «Empirical» pour une bonne raison et il existe un risque de confusion entre les fonctions de mode intrinsèque (les composants additifs individuels). D'autre part, la méthode est très intuitive et peut être utile pour une inspection visuelle rapide de la cyclicité.
la source
En référence au message de Rob Hyndman ci-dessus https://stats.stackexchange.com/a/1214/70282
La fonction find.freq fonctionne à merveille. Sur le jeu de données quotidien que j’utilise, il a correctement calculé la fréquence à 7.
Lorsque je l’essayais uniquement les jours de la semaine, la fréquence était de 23, ce qui est remarquablement proche de 21,42857 = 29,6 * 5/7, ce qui correspond au nombre moyen de jours de travail par mois. (Ou à l'inverse 23 * 7/5 est 32.)
En regardant mes données quotidiennes, j'ai expérimenté l'idée de prendre la première période, de calculer la moyenne par la suite, puis de trouver la prochaine période, etc. Voir ci-dessous:
Ce qui précède donne (7,28) ou (7,35) selon que le seq commence par 1 ou f. (Voir le commentaire ci-dessus.)
Ce qui impliquerait que les périodes saisonnières pour les msts (...) soient de (7,28) ou (7,35).
La logique semble sensible aux conditions initiales étant donné la sensibilité des paramètres de l'algorithme. La moyenne de 28 et 35 est de 31,5, ce qui est proche de la durée moyenne d'un mois.
Je soupçonne avoir réinventé la roue, quel est le nom de cet algorithme? Y at-il une meilleure mise en œuvre dans R quelque part?
Plus tard, j'ai utilisé le code ci-dessus en essayant tous les départs de 1 à 7 et j'ai eu 35,35,28,28,28,28,28 pour la deuxième période. La moyenne s’élève à 30, ce qui correspond au nombre moyen de jours dans un mois. Intéressant...
Des pensées ou des commentaires?
la source
On peut aussi utiliser le test de Ljung-Box pour déterminer quelle différence saisonnière atteint la meilleure stationnarité. Je travaillais sur un sujet différent et je l’utilisais en fait aux mêmes fins. Essayez différentes périodes telles que 3 à 24 pour des données mensuelles. Et testez chacune d’elles par Ljung-Box et stockez les résultats du Chi-Square. Et choisissez la période avec la plus basse valeur de Khi-deux.
Voici un code simple pour le faire.
la source