2014-12-05 5 views
6

Non riesco a far funzionare tutto questo per i miei dati, quindi prima sto cercando un esempio concreto che sia molto simile. Ecco l'dataframe:UnboundLocalError: variabile locale 'x' referenziata prima dell'assegnazione. Uso corretto di tsplot nel pacchetto Seaborn per un dataframe?

In [56]: 

idx = pd.DatetimeIndex(start='1990-01-01', freq='d', periods=5) 
data= pd.DataFrame({('A','a'):[1,2,3,4,5], 
        ('A','b'):[6,7,8,9,1], 
        ('B','a'):[2,3,4,5,6], 
        ('B','b'):[7,8,9,1,2]}, idx) 
Out[56]: 
A B 
a b a b 
1990-01-01 1 6 2 7 
1990-01-02 2 7 3 8 
1990-01-03 3 8 4 9 
1990-01-04 4 9 5 1 
1990-01-05 5 1 6 2 

Quindi quello che sto sperando di fare è la trama di una serie di tempo con una linea per la tendenza centrale tra le variabili (ogni colonna) per ciascuna osservazione (ogni giorno nell'indice), con un'area ombreggiata che indica lo stimatore di errore specificato (probabilmente solo il 95% ci) delle osservazioni corrispondenti a ciascun giorno.

Ho provato questo:

sns.tsplot(data, time=idx) 

Ma ottengo il seguente errore:

UnboundLocalError       Traceback (most recent call last) 
<ipython-input-57-fa07e08ead95> in <module>() 
     5      ('B','b'):[7,8,9,1,2]}, idx) 
     6 
----> 7 sns.tsplot(data, time=idx) 

C:\Users\Patrick\Anaconda\lib\site-packages\seaborn\timeseries.pyc in tsplot(data, time, unit, condition, value, err_style, ci, interpolate, color, estimator, n_boot, err_palette, err_kws, legend, ax, **kwargs) 
    253 
    254  # Pad the sides of the plot only when not interpolating 
--> 255  ax.set_xlim(x.min(), x.max()) 
    256  x_diff = x[1] - x[0] 
    257  if not interpolate: 

UnboundLocalError: local variable 'x' referenced before assignment 

La sintassi per tsplot è:

sns.tsplot(data, time=None, unit=None, condition=None, value=None, err_style='ci_band', ci=68, interpolate=True, color=None, estimator=<function mean at 0x00000000044F2C18>, n_boot=5000, err_palette=None, err_kws=None, legend=True, ax=None, **kwargs) 

Così sto fornendo miei dati con l'indice come argomento del tempo, ma non sono sicuro di cosa sto facendo male. Non penso di aver bisogno di altri argomenti per le parole chiave, ma forse questo è il problema.

Se faccio questo con una matrice di dimensioni (unità di tempo) invece:

sns.tsplot(data.values.T, time=idx) 

ottengo i risultati attesi (tranne senza i timestamp sono le xlabels):

enter image description here

Ma qual è il modo giusto per farlo con un dataframe? So che deve essere in "forma lunga", ma non sono abbastanza sicuro di cosa significherebbe per questo specifico frame.

+1

UnboundLocalError mi sembra un bug. . . – mgilson

+0

Avevo paura di ciò. Ho visto qualcosa di simile che sembrava essere stato risolto installando il pacchetto statsmodels, ma ho questo e ho appena aggiornato e ripreso lo stesso codice per essere sicuro. – pbreach

+0

Non sono esperto qui, ma sembra che questo potrebbe accadere se il filtro groupby non produce alcun risultato: https://github.com/mwaskom/seaborn/blob/master/seaborn/timeseries.py#L201 - - La condizione di default per un dataframe è calcolata sulla riga 108, se è del tutto utile ... (Scusate, non molto di un ragazzo panda me stesso ...) – mgilson

risposta

8

Ho finito per capirlo. Fondamentalmente il primo posto che avrei dovuto cercare era here nella sezione intitolata "Specificare i dati di input con DataFrames di forma estesa". Quello che ho dovuto fare è stato questo:

data.reset_index(inplace=True) 
data.columns = np.arange(len(data.columns)) 
melted = pd.melt(data, id_vars=0) 

La prima linea si muove il DatetimeIndex nella propria colonna e imposta un inplace indice intero predefinito. La seconda riga fa lo stesso per le intestazioni tranne che per eliminarle (dovevo farlo perché non sembra possibile eseguire il raggruppamento con un multiindice). Infine abbiamo sciogliamo i dati creando dataframe che assomiglia a questo:

In [120]: 

melted 
Out[120]: 
0 variable value 
0 1990-01-01 1 1 
1 1990-01-02 1 2 
2 1990-01-03 1 3 
3 1990-01-04 1 4 
4 1990-01-05 1 5 
5 1990-01-01 2 6 
6 1990-01-02 2 7 
7 1990-01-03 2 8 
8 1990-01-04 2 9 
9 1990-01-05 2 1 
10 1990-01-01 3 2 
11 1990-01-02 3 3 
12 1990-01-03 3 4 
13 1990-01-04 3 5 
14 1990-01-05 3 6 
15 1990-01-01 4 7 
16 1990-01-02 4 8 
17 1990-01-03 4 9 
18 1990-01-04 4 1 
19 1990-01-05 4 2 

Ora, dopo il dataframe è pronto posso usare tsplot in questo modo:

sns.tsplot(melted, time=0, unit='variable', value='value') 

che nel mio caso è più o meno lo stesso come se ho fatto:

sns.tsplot(data.T.values, idx) 
plt.xlabel('0') 
plt.ylabel('value') 

tranne se ho aggiunto tutte le condizioni quindi tsplot sarebbe tracciare le altre serie e fare una leggenda per me.

Sarebbe bello è tsplot potrebbe almeno tracciare le date come data e ora data la natura della funzione. Penso che usare l'array trasposto sarà un'opzione molto più semplice per la mia applicazione invece di usare direttamente un DataFrame.