Estrarre punti dati dalla media mobile?


15

È possibile estrarre punti dati dallo spostamento di dati medi?

In altre parole, se un insieme di dati ha solo medie mobili semplici dei precedenti 30 punti, è possibile estrarre i punti dati originali?

Se é cosi, come?


1
La risposta è un sì qualificato, ma la procedura esatta dipende da come viene trattato il segmento iniziale di dati. Se viene semplicemente lasciato cadere, hai effettivamente perso 15 pezzi di dati, lasciandoti con un sistema indeterminato di equazioni lineari. Il risultato è che esistono molte risposte valide in generale, ma è comunque possibile fare qualche progresso se si utilizzano (a) finestre più brevi (o alcune procedure di questo tipo) per le 15 medie mobili iniziali o (b) è possibile specificare ulteriori vincoli su la soluzione (circa 15 dimensioni di vincoli ...). In che situazione ti trovi?
whuber

@whuber Grazie mille per lo sguardo! Ho 2000 punti. Il primo punto MA è molto probabilmente una media dei primi 30 punti originali. La precisione è seconda a un risultato generalmente corretto, in particolare le ipotesi più valide nei punti più "recenti". Puoi consigliarmi un metodo relativamente semplice? Grazie in anticipo!

1
(se impieghi più di cinque minuti a scrivere un commento ...). Quello che volevo scrivere è che puoi pensare alla media come a una moltiplicazione matriciale. Le righe nel mezzo avranno 1/30 * [1 1 1 ...] prima della diagonale. La domanda è: come gestisci i punti ai bordi del tuo vettore per rendere la matrice invertibile. Puoi farlo supponendo che siano il risultato della media su meno elementi o pensi ad altri vincoli. Si noti che mentre un'inversione di matrice è un modo semplice per capirla, non è la più efficiente. Probabilmente vuoi usare una FFT per farlo.
fabee,

Risposte:


4

+1 alla risposta di fabee, che è completa. Solo una nota per tradurlo in R, in base ai pacchetti che ho trovato per fare le operazioni a portata di mano. Nel mio caso, avevo dati che sono previsioni di temperatura NOAA su base trimestrale: gennaio-febbraio-marzo, febbraio-marzo-aprile, marzo-aprile-maggio, ecc. E volevo dividerli in (approssimativo) valori mensili, supponendo che la temperatura di ciascun periodo di tre mesi sia essenzialmente una media.

library (Matrix)
library (matrixcalc)

# Feb-Mar-Apr through Nov-Dec-Jan temperature forecasts:

qtemps <- c(46.0, 56.4, 65.8, 73.4, 77.4, 76.2, 69.5, 60.1, 49.5, 41.2)

# Thus I need a 10x12 matrix, which is a band matrix but with the first
# and last rows removed so that each row contains 3 1's, for three months.
# Yeah, the as.matrix and all is a bit obfuscated, but the results of
# band are not what svd.inverse wants.

a <- as.matrix (band (matrix (1, nrow=12, ncol=12), -1, 1)[-c(1, 12),])
ai <- svd.inverse (a)

mtemps <- t(qtemps) %*% t(ai) * 3

Il che funziona benissimo per me. Grazie @fabee.

EDIT: OK, ri-traducendo la mia R in Python, ottengo:

from numpy import *
from numpy.linalg import *

qtemps = transpose ([[46.0, 56.4, 65.8, 73.4, 77.4, 76.2, 69.5, 60.1, 49.5, 41.2]])

a = tril (ones ((12, 12)), 2) - tril (ones ((12, 12)), -1)
a = a[0:10,:]

ai = pinv (a)

mtemps = dot (ai, qtemps) * 3

(Il cui debug ha richiesto molto più tempo rispetto alla versione R. Prima perché non ho familiarità con Python come con R, ma anche perché R è molto più utilizzabile in modo interattivo.)


@Gracchus: Siamo spiacenti, non un tipo C ++, ma potresti trovare quello che ti serve nella libreria di algebra lineare Armadillo C ++ ( arma.sourceforge.net ), che è disponibile anche in R tramite il pacchetto RcppArmadillo.
Wayne,

OK, vedi se funziona per te. In tal caso, potresti scegliere la mia risposta ;-)
Wayne,

Le migliori pratiche di FYI in Python sono l'importazione assoluta: python.org/dev/peps/pep-0008/#imports che rende molto più facile leggere il codice di altre persone, perché in realtà sai da dove provengono le funzioni invece di dover cerca ognuno che non conosci. Vorrei che fosse standard in R fare lo stesso. Avendo di ricercare ogni piccolo funzioni di qualcun altro codice macina davvero i miei ingranaggi ...
wordsforthewise

Inoltre, notebook Jupyter per l'interattività di Python o IPython.
parole per

17

xn=2000=30y=Axx

A=130(1...10...001...10...0...1...100...01...1)

3030y19702000

x1,...,x2000y1y2

x1,...,xnxyx

A3030AA

AAz=AyxyAz

2000x

ricostruzione del segnale originale dalla media mobile usando lo pseudoinverso

Molti programmi numerici offrono pseudo-inverse (ad esempio Matlab, numpy in python, ecc.).

Ecco il codice Python per generare i segnali dal mio esempio:

from numpy import *
from numpy.linalg import *
from matplotlib.pyplot import *
# get A and its inverse     
A = (tril(ones((2000,2000)),-1) - tril(ones((2000,2000)),-31))/30.
A = A[30:,:]
pA = pinv(A) #pseudo inverse

# get x
x = random.randn(2000) + 5
y = dot(A,x)

# reconstruct
x2 = dot(pA,y)

plot(x,label='original x')
plot(y,label='averaged x')
plot(x2,label='reconstructed x')
legend()
show()

Spero possa aiutare.


Questa è un'ottima risposta, ma penso che ti sbagli quando hai detto che "minimizza la distanza quadratica tra y e Az". In effetti y e Az sono la stessa cosa. Ciò che è minimizzato è la norma di z che funziona bene per i segnali del mondo reale che ho provato, ma non è così buona se il tuo segnale originale ha molti valori anomali.
gdelfino,

Non sono sicuro di seguire. y e Ax sono la stessa cosa, ma non y e Az È vero che minimizza anche la norma di z. Inoltre non vedo perché non funziona per i miei esempi. La linea blu e quella rossa si abbinano abbastanza bene. Mi manca qualcosa nel tuo commento?
Fabee,

y è la media mobile calcolata dal segnale originale x moltiplicando per A. Questa procedura ci fornisce un segnale z che ha la stessa media mobile y. Quindi y = Az Quindi solo la norma di z viene minimizzata. Se il segnale originale ha un valore di norma elevato, la procedura non darà buoni risultati. Di seguito è riportato un segnale di esempio con un valore di norma elevato:
gdelfino,

{42,8, -33,7, 13,2, -45,6, 10,2, 35,8, -41,4, 20.253, 43.3429, -33.2735, 13.6135, -45.1067, 10.6346, 36.1352, -40.9703, 20.6616, 43.6796, -32.8966, 14.0406, -44.7001, 10.9988 , 36.4675, -40.7277, 20.8823, 43.7878, -32.7415, 13.9951, -44.7947, 11.044, 36.3873, -40.7117, 20.7505, 43.8204, -32.9399, 13.9129, -44.9549, 10.8703, 36.1559, -40.4784, 2059 , 13.5468, -45.2374, 10.3787, 35.8235, -41.5161, 19.9717, 43.0658, -33.7125, 13.0321}
gdelfino,

Si prega di utilizzare una dimensione di Windows di 8 per il segnale sopra. In questo modo il segnale filtrato ha una forma molto diversa dal segnale originale.
gdelfino,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.