Aqui está o meu experimento:
Estou usando a findPeaks
função no pacote quantmod :
Quero detectar picos "locais" dentro de uma tolerância 5, ou seja, os primeiros locais após a série cronológica caírem dos picos locais em 5:
aa=100:1
bb=sin(aa/3)
cc=aa*bb
plot(cc, type="l")
p=findPeaks(cc, 5)
points(p, cc[p])
p
A saída é
[1] 3 22 41
Parece errado, pois espero mais "picos locais" do que 3 ...
Alguma ideia?
r
time-series
Luna
fonte
fonte
findPeaks
aparece na minha resposta, @Adam. BTW, o pacote é "quantmod" .Respostas:
A fonte desse código é obtida digitando seu nome no prompt R. A saída é
O teste
x[pks - 1] - x[pks] > thresh
compara cada valor de pico com o valor imediatamente seguinte na série (não com o próximo nível da série). Ele usa uma estimativa (bruta) do tamanho da inclinação da função imediatamente após o pico e seleciona apenas os picos em que a inclinação excedethresh
de tamanho. No seu caso, apenas os três primeiros picos são suficientemente nítidos para passar no teste. Você detectará todos os picos usando o padrão:fonte
Concordo com a resposta do whuber, mas só queria acrescentar que a parte "+2" do código, que tenta alterar o índice para corresponder ao pico recém-encontrado, na verdade 'ultrapassa' e deve ser "+1". por exemplo, no exemplo em questão, obtemos:
quando destacamos esses picos encontrados em um gráfico (vermelho negrito):
vemos que eles estão consistentemente a 1 ponto do pico real.
consequentemente
deve ser
pks[x[pks] - x[pks + 1] > thresh]
oupks[x[pks] - x[pks - 1] > thresh]
ATUALIZAÇÃO GRANDE
seguindo minha própria busca para encontrar uma função adequada de localização de pico, escrevi isso:
um 'pico' é definido como um máximo local, com
m
pontos em ambos os lados menores que ele. portanto, quanto maior o parâmetrom
, mais rigoroso é o procedimento de pico de financiamento. assim:a função também pode ser usada para encontrar mínimos locais de qualquer vetor seqüencial
x
viafind_peaks(-x)
.Nota: agora coloquei a função no gitHub se alguém precisar: https://github.com/stas-g/findPeaks
fonte
Eek: atualização menor. Eu tive que mudar duas linhas de código, os limites (adicionar -1 e +1) para alcançar a equivalência com a função de Stas_G (estava encontrando muitos "picos extras" em conjuntos de dados reais). Peço desculpas a qualquer pessoa que se desvie muito pouco do meu post original.
Eu tenho usado o algoritmo de encontrar picos do Stas_g há algum tempo. Foi benéfico para mim em um dos meus projetos posteriores devido à sua simplicidade. No entanto, eu precisava usá-lo milhões de vezes para um cálculo, então eu o reescrevi no Rcpp (consulte o pacote Rcpp). É aproximadamente 6x mais rápido que a versão R em testes simples. Se alguém estiver interessado, adicionei o código abaixo. Espero que ajude alguém, Saúde!
Algumas pequenas advertências. Esta função retorna os índices de pico na ordem inversa do código R. Requer uma função interna de sinal C ++, que eu incluí. Não foi completamente otimizado, mas não são esperados mais ganhos de desempenho.
fonte
for(q = lb; q < rb; ++q){ if(vY(q) > vY(i+1)){ isGreatest = false; } }
como a última corrida através do laço "ganha", fazendo o equivalente a:isGreatest = vY(rb-1) <= vY(rb)
. Para conseguir o que o comentário acima que as alegações de linha, o loop for precisaria ser alterado para:for(q = lb; isGreatest && (q < rb); ++q){ isGreatest = (vY(q) <= vY(i+1)) }
Primeiramente: o algoritmo também chama falsamente uma queda à direita de um platô plano, pois
sign(diff(x, na.pad = FALSE))
será 0 e -1, de modo que seu diff também será -1. Uma correção simples é garantir que a diferença de sinal que antecede a entrada negativa não seja zero, mas positiva:Segundo: o algoritmo fornece resultados muito locais, por exemplo, um 'up' seguido de um 'down' em qualquer execução de três termos consecutivos na sequência. Se alguém está interessado no máximo local de uma função contínua barulhenta, então - provavelmente existem outras coisas melhores por aí, mas esta é a minha solução barata e imediata
suavizar os dados levemente. Empregue também o controle acima mencionado contra queda plana e depois queda.
filtre esses candidatos comparando, para uma versão suavizada, a média dentro de uma janela centralizada em cada pico com a média dos termos locais externos.
fonte
É verdade que a função também identifica o fim dos platôs, mas acho que há outra solução mais fácil: como o primeiro diff de um pico real resultará em '1' e em '-1', o segundo diff seria '-2', e podemos verificar diretamente
fonte
usando Numpy
ou
usando pandas
fonte