Tenho uma série temporal um tanto barulhenta que paira em diferentes níveis.
Por exemplo, os seguintes dados:
Eu tenho os dados de linha sólida disponíveis e gostaria de obter uma estimativa para a linha tracejada. Deve ser constante por partes.
Quais algoritmos são apropriados para testar aqui?
Até agora, minhas idéias pairam em torno de splines P de 0 grau (mas como descobrir onde colocar os nós?) Ou em modelos de quebra estrutural. Uma árvore de regressão é a melhor ideia que tenho atualmente, mas, idealmente, eu estaria procurando um método que levasse em conta o fato de que os dois níveis em y = 250 estão com valores y iguais. Se bem entendi, uma árvore de regressão dividiria esses dois intervalos em dois grupos diferentes, cada um com uma média diferente.
O código R que o gerou é este:
set.seed(20181118)
true_fct = stepfun(c(100, 200, 250), c(200, 250, 300, 250))
x = 1:400
y = true_fct(x) + rt(length(x), df=1)
plot(x, y, type="l")
lines(x, true_fct(x), lty=2, lwd=3)
fonte
Respostas:
Um método simples e robusto para lidar com esse ruído é calcular medianas.
Uma mediana contínua sobre uma janela curta detectará todos os saltos, exceto os menores, enquanto as medianas da resposta dentro de intervalos entre os saltos detectados estimarão de forma robusta seus níveis. (Você pode substituir esta última estimativa por qualquer estimativa robusta que não seja afetada pelos valores discrepantes.)
Você deve ajustar essa abordagem com dados reais ou simulados para obter taxas de erro aceitáveis. Por exemplo, para a simulação na pergunta, achei bom usar o segundo e o 98º percentil para definir limites para detectar os saltos. Em outras circunstâncias - como quando muitos saltos podem ocorrer - mais percentis centrais funcionariam melhor.
Aqui está o resultado mostrando (a) os três saltos como pontos vermelhos e (b) os quatro níveis estimados como linhas azuis claras.
Estima-se que os saltos ocorram nos índices 100, 200, 250 (que é exatamente onde a simulação os faz ocorrer) e os níveis resultantes são estimados em 199,6, 249,8, 300,0 e 250,2: tudo dentro de 0,4 dos valores subjacentes verdadeiros.
Esse excelente comportamento persiste com repetidas simulações (removendo o
set.seed
comando no início).Aqui está o
R
código.fonte
zoo::rollmedian
uma função semelhante para simplificar seu código.zoo
mas eleito para não usá-lo, porque sou preguiçoso! Era mais rápido e fácil escreverrollmed
do que revisar as chamadas de argumento para qualquer função que já estivesse disponível. Além disso, gosto derollmed
ilustrar com clareza o que estou fazendo, em vez de ocultar os detalhes atrás de uma caixa preta.zoo
, eu era incerto se você não usá-lo por opção ou por acidente Boa resposta, em qualquer caso +1.)Se você ainda estiver interessado em suavizar as penalidades L0, daria uma olhada na seguinte referência: "Visualização de alterações genômicas por suavização segmentada usando uma penalidade L0" - DOI: 10.1371 / journal.pone.0038230 (uma boa introdução à O Whittaker mais suave pode ser encontrado no artigo P. Eilers "Um perfeito mais suave" - DOI: 10.1021 / ac034173t). Obviamente, para atingir seu objetivo, você precisa trabalhar um pouco em torno do método.
Em princípio, você precisa de 3 ingredientes:
Obviamente, você precisaria também de uma maneira de selecionar a quantidade ideal de suavização. Isso é feito pelos meus olhos de carpinteiro neste exemplo. Você pode usar os critérios em DOI: 10.1371 / journal.pone.0038230 (pág. 5, mas eu não tentei no seu exemplo).
Você encontrará um pequeno código abaixo. Deixei alguns comentários como guia.
PS. Esta é minha primeira resposta no Cross Validated. Espero que seja útil e claro o suficiente :-)
fonte
Eu consideraria o uso de Outliers de papel de Ruey Tsay , mudanças de nível e mudanças de variação no modelo de diferenciação de séries temporais com os outliers AR1 e 21.
Desativamos a diferença e as mudanças de nível são especificamente mencionadas.
fonte