2015-12-28 6 views
5

Ich habe zwei numpy Arrays light_points und time_points und möchte einige Zeitreihenanalyse-Methoden für diese Daten verwenden.Zeitreihenanalyse - ungleichmäßige Messungen - pandas + statsmodels

Ich versuchte dann das:

import statsmodels.api as sm 
import pandas as pd 
tdf = pd.DataFrame({'time':time_points[:]}) 
rdf = pd.DataFrame({'light':light_points[:]}) 
rdf.index = pd.DatetimeIndex(freq='w',start=0,periods=len(rdf.light)) 
#rdf.index = pd.DatetimeIndex(tdf['time']) 

Das funktioniert aber ist die richtige Sache nicht zu tun. Tatsächlich sind die Messungen nicht gleichmäßig zeitbeabstandeten und wenn ich nur die time_points Pandas Dataframe als Index meines Rahmen erklären, ich erhalte eine Fehlermeldung:

rdf.index = pd.DatetimeIndex(tdf['time']) 

decomp = sm.tsa.seasonal_decompose(rdf) 

elif freq is None: 
raise ValueError("You must specify a freq or x must be a pandas object with a timeseries index") 

ValueError: You must specify a freq or x must be a pandas object with a timeseries index 

Ich weiß nicht, wie dies zu korrigieren. Es scheint auch, dass Pandas TimeSeries veraltet sind.

Ich versuchte dies:

rdf = pd.Series({'light':light_points[:]}) 
rdf.index = pd.DatetimeIndex(tdf['time']) 

Aber es gibt mir eine Länge Mismatch:

ValueError: Length mismatch: Expected axis has 1 elements, new values have 122 elements 

Trotzdem verstehe ich nicht, wo es aus, als rdf kommt [ 'Licht'] und TDF [ ‚Zeit‘] sind gleich lang ...

Schließlich versuchte ich durch meine rdf als Pandas Serie definieren:

rdf = pd.Series(light_points[:],index=pd.DatetimeIndex(time_points[:])) 

Und ich bekomme diese:

ValueError: You must specify a freq or x must be a pandas object with a timeseries index 

Dann habe ich versucht, den Index stattdessen ersetzt durch

pd.TimeSeries(time_points[:]) 

Und es gibt mir einen Fehler auf der seasonal_decompose Methode Linie:

AttributeError: 'Float64Index' object has no attribute 'inferred_freq' 

Wie kann ich mit ungleichmäßigen Daten arbeiten? Ich habe überlegt, ein ungefähr gleichmäßiges Zeit-Array zu erstellen, indem ich viele unbekannte Werte zwischen den vorhandenen Werten hinzufüge und diese Punkte durch Interpolation "evaluiere", aber ich denke, es könnte eine sauberere und einfachere Lösung geben.

+0

Sie die Änderung erhöhen, um eine gute Antwort zu erhalten, wenn Du postest ein [minimales, vollständiges und verifizierbares Beispiel] (http://stackoverflow.com/help/mcve). –

Antwort

8

seasonal_decompose() erfordert ein freq, die entweder als Teil der DateTimeIndex Meta-Informationen zur Verfügung gestellt wird, kann durch pandas.Index.inferred_freq oder auch durch den Benutzer als integer zu entnehmen, dass die Anzahl der Perioden pro Zyklus gibt. z.B., 12 für monatlich (von docstring für seasonal_mean):

def seasonal_decompose(x, model="additive", filt=None, freq=None): 
    """ 
    Parameters 
    ---------- 
    x : array-like 
     Time series 
    model : str {"additive", "multiplicative"} 
     Type of seasonal component. Abbreviations are accepted. 
    filt : array-like 
     The filter coefficients for filtering out the seasonal component. 
     The default is a symmetric moving average. 
    freq : int, optional 
     Frequency of the series. Must be used if x is not a pandas 
     object with a timeseries index. 

Zur Veranschaulichung - Stichprobe Daten:

length = 400 
x = np.sin(np.arange(length)) * 10 + np.random.randn(length) 
df = pd.DataFrame(data=x, index=pd.date_range(start=datetime(2015, 1, 1), periods=length, freq='w'), columns=['value']) 

<class 'pandas.core.frame.DataFrame'> 
DatetimeIndex: 400 entries, 2015-01-04 to 2022-08-28 
Freq: W-SUN 

decomp = sm.tsa.seasonal_decompose(df) 
data = pd.concat([df, decomp.trend, decomp.seasonal, decomp.resid], axis=1) 
data.columns = ['series', 'trend', 'seasonal', 'resid'] 

Data columns (total 4 columns): 
series  400 non-null float64 
trend  348 non-null float64 
seasonal 400 non-null float64 
resid  348 non-null float64 
dtypes: float64(4) 
memory usage: 15.6 KB 

So weit, so gut - jetzt zufällig Elemente aus der DateTimeIndex dropping um ungleiche Raumdaten zu erzeugen:

df = df.iloc[np.unique(np.random.randint(low=0, high=length, size=length * .8))] 

<class 'pandas.core.frame.DataFrame'> 
DatetimeIndex: 222 entries, 2015-01-11 to 2022-08-21 
Data columns (total 1 columns): 
value 222 non-null float64 
dtypes: float64(1) 
memory usage: 3.5 KB 

df.index.freq 

None 

df.index.inferred_freq 

None 

die seasonal_decomp dieser Daten Running ‚funktioniert‘:

decomp = sm.tsa.seasonal_decompose(df, freq=52) 

data = pd.concat([df, decomp.trend, decomp.seasonal, decomp.resid], axis=1) 
data.columns = ['series', 'trend', 'seasonal', 'resid'] 

DatetimeIndex: 224 entries, 2015-01-04 to 2022-08-07 
Data columns (total 4 columns): 
series  224 non-null float64 
trend  172 non-null float64 
seasonal 224 non-null float64 
resid  172 non-null float64 
dtypes: float64(4) 
memory usage: 8.8 KB 

Die Frage ist - wie nützlich das Ergebnis. Auch ohne Lücken in den Daten, die Rückschlüsse auf saisonale Muster (siehe Beispiel für die Verwendung von .interpolate() im release notes erschweren, qualifiziert statsmodels dieses Verfahren wie folgt:

Notes 
----- 
This is a naive decomposition. More sophisticated methods should 
be preferred. 

The additive model is Y[t] = T[t] + S[t] + e[t] 

The multiplicative model is Y[t] = T[t] * S[t] * e[t] 

The seasonal component is first removed by applying a convolution 
filter to the data. The average of this smoothed series for each 
period is the returned seasonal component. 
+0

Warum hast du 'freq = 52' verwendet - warum 52 nicht eine andere Nummer? – Rocketq

+0

Es ist schon eine Weile her, aber Ich glaube, weil mein Beispiel wöchentliche Zufallsdaten verwendet - siehe oben. – Stefan

Verwandte Themen