Este post é a continuação de outro post relacionado a um método genérico para detecção de outlier em séries temporais . Basicamente, neste ponto, estou interessado em uma maneira robusta de descobrir a periodicidade / sazonalidade de uma série temporal genérica afetada por muito ruído. Do ponto de vista do desenvolvedor, eu gostaria de uma interface simples como:
unsigned int discover_period(vector<double> v);
Onde v
está o array que contém as amostras e o valor de retorno é o período do sinal. O ponto principal é que, novamente, não posso fazer nenhuma suposição sobre o sinal analisado. Eu já tentei uma abordagem baseada na autocorrelação de sinal (detectando os picos de um correlograma), mas não é robusta como eu gostaria.
time-series
algorithms
frequency
real-time
gianluca
fonte
fonte
Respostas:
Se você realmente não tem idéia de qual é a periodicidade, provavelmente a melhor abordagem é encontrar a frequência correspondente ao máximo da densidade espectral. No entanto, o espectro em baixas frequências será afetado pela tendência; portanto, você deve prejudicar a série primeiro. A seguinte função R deve fazer o trabalho para a maioria das séries. Está longe de ser perfeito, mas já o testei em algumas dezenas de exemplos e parece funcionar bem. Ele retornará 1 para dados que não possuem periodicidade forte e a duração do período caso contrário.
Atualização: versão 2 da função. Isso é muito mais rápido e parece ser mais robusto.
fonte
findfrequency
Se você espera que o processo seja estacionário - a periodicidade / sazonalidade não mudará ao longo do tempo -, algo como um periodograma do qui-quadrado (veja, por exemplo, Sokolove e Bushell, 1978) pode ser uma boa escolha. É comumente usado na análise de dados circadianos que podem ter quantidades extremamente grandes de ruído, mas espera-se que tenha periodicidades muito estáveis.
Essa abordagem não pressupõe a forma da forma de onda (além de ser consistente de ciclo para ciclo), mas exige que qualquer ruído seja de média constante e não correlacionado com o sinal.
As duas últimas linhas são apenas um exemplo, mostrando que ele pode identificar o período de uma função trigonométrica pura, mesmo com muito ruído aditivo.
Como está escrito, o último argumento (
alpha
) na chamada é supérfluo; a função simplesmente retorna o 'melhor' período que pode encontrar; remova o comentário da primeirareturn
declaração e comente a segunda para que ela retorne uma lista de todos os períodos significativos no nívelalpha
.Essa função não realiza nenhum tipo de verificação de sanidade para garantir que você tenha colocado períodos identificáveis, nem (pode) funcionar com períodos fracionários, nem existe algum tipo de controle de comparação múltiplo incorporado, se você decidir olhe para vários períodos. Mas fora isso, deve ser razoavelmente robusto.
fonte
Você pode definir o que deseja de forma mais clara (para você mesmo, se não estiver aqui). Se o que você está procurando é o período estacionário estatisticamente mais significativo contido nos seus dados barulhentos, há essencialmente duas rotas a seguir:
1) calcular uma estimativa robusta de autocorrelação e obter o coeficiente máximo
2) calcular uma estimativa robusta da densidade espectral de potência e obter o máximo do espectro
O problema do número 2 é que, para qualquer série temporal barulhenta, você obtém uma grande quantidade de energia em baixas frequências, dificultando a distinção. Existem algumas técnicas para resolver esse problema (ou seja, pré-branquear e estimar o PSD), mas se o período real dos dados for longo o suficiente, a detecção automática será duvidosa.
Sua melhor aposta é provavelmente implementar uma rotina robusta de autocorrelação, como pode ser encontrada no capítulo 8.6, 8.7 em Estatísticas robustas - teoria e métodos de Maronna, Martin e Yohai. Procurar no Google por "durbin-levinson robusto" também produzirá alguns resultados.
Se você está apenas procurando uma resposta simples, não tenho certeza de que exista. A detecção de períodos em séries temporais pode ser complicada, e solicitar uma rotina automatizada que possa executar mágica pode ser demais.
fonte
Você pode usar a transformação de Hilbert da teoria DSP para medir a frequência instantânea de seus dados. O site http://ta-lib.org/ possui código-fonte aberto para medir o período dominante do ciclo de dados financeiros; a função relevante é chamada HT_DCPERIOD; você pode usar isso ou adaptar o código aos seus propósitos.
fonte
Uma abordagem diferente poderia ser a decomposição do modo empírico. O pacote R é chamado EMD desenvolvido pelo inventor do método:
O método foi marcado como 'Empírico' por um bom motivo e existe o risco de que as Funções do Modo Intrínseco (os componentes aditivos individuais) se misturem. Por outro lado, o método é muito intuitivo e pode ser útil para uma inspeção visual rápida da ciclicidade.
fonte
Em referência à postagem de Rob Hyndman acima https://stats.stackexchange.com/a/1214/70282
A função find.freq funciona de maneira brilhante. No conjunto de dados diário que estou usando, calculou corretamente a frequência como 7.
Quando o experimentei apenas nos dias da semana, mencionou que a frequência é 23, o que é notavelmente próximo de 21,42857 = 29,6 * 5/7, que é o número médio de dias úteis em um mês. (Ou, inversamente, 23 * 7/5 é 32.)
Revendo meus dados diários, experimentei um palpite de tirar o primeiro período, calcular a média desse valor e, em seguida, encontrar o próximo período, etc. Veja abaixo:
O exemplo acima fornece (7,28) ou (7,35), dependendo de seq começar com 1 ou f. (Veja o comentário acima.)
O que implicaria que os períodos sazonais para msts (...) fossem (7,28) ou (7,35).
A lógica parece sensível às condições iniciais, dada a sensibilidade dos parâmetros do algoritmo. A média de 28 e 35 é 31,5, o que está próximo da duração média de um mês.
Eu suspeito que reinventei a roda, qual é o nome desse algoritmo? Existe uma melhor implementação em R em algum lugar?
Mais tarde, executei o código acima ao tentar todas as partidas de 1 a 7 e obtive 35,35,28,28,28,28,28 pelo segundo período. A média chega a 30, que é o número médio de dias em um mês. Interessante...
Quaisquer pensamentos ou comentários?
fonte
Pode-se também usar o teste de Ljung-Box para descobrir qual diferença sazonal atinge a melhor estacionariedade. Eu estava trabalhando em um assunto diferente e usei isso realmente para os mesmos fins. Tente períodos diferentes, como 3 a 24, para obter dados mensais. E teste cada um deles pela Ljung-Box e armazene os resultados do Chi-Square. E escolha o período com o menor valor do qui-quadrado.
Aqui está um código simples para fazer isso.
fonte