2016-06-11 39 views
5

Sto tentando di creare un grafico di serie temporali a 3 righe basato sui seguenti dati Long Dataframe, in un grafico di Sovraccarico settimana x, in cui ogni Cluster è una linea diversa.Gli orari vengono stampati con ombreggiatura minima/massima utilizzando Seaborn

Ho più osservazioni per ciascuna coppia (Cluster, Week) (5 per ogni atm, avrà 1000). Vorrei che i punti sulla linea fossero il valore di sovraccarico medio per quella coppia specifica (Cluster, Week) e la banda fosse i valori min/max di essa.

Attualmente utilizzando il seguente frammento di codice per tracciare, ma io non ricevo alcuna linea, come io non so quale unità per specificare utilizzando il dataframe corrente:

ax14 = sns.tsplot(data = long_total_cluster_capacity_overload_df, value = "Overload", time = "Week", condition = "Cluster") 

GIST Data

Ho la sensazione che debba ancora modificare il mio dataframe, ma non ho idea di come. Alla ricerca di un risultato finale che assomiglia a questo enter image description here

+0

meglio che ho potuto venire con finora sta usando sns.pointplot e ottenere questo: https://gyazo.com/425b31b23f9d5009c12502f3113361ef –

+0

onestamente, è che trama non esattamente quello che stai cercando per? ti piacerebbe che l'ombreggiatura inter-line sia meno e le linee dei bordi siano più scure? –

+0

Sembra simile a quello che sto cercando, ma se lo espongo, sono intervalli di confidenza effettivi (linee verticali per ogni punto), quindi non una sequenza temporale continua per così dire. E sì, vorrei che l'ombreggiatura inter-line fosse inferiore. –

risposta

3

in base al largo this incredible answer, sono stato in grado di creare una patch scimmia per fare in modo bello quello che stai cercando. Grafico

import pandas as pd 
import seaborn as sns  
import seaborn.timeseries 

def _plot_range_band(*args, central_data=None, ci=None, data=None, **kwargs): 
    upper = data.max(axis=0) 
    lower = data.min(axis=0) 
    #import pdb; pdb.set_trace() 
    ci = np.asarray((lower, upper)) 
    kwargs.update({"central_data": central_data, "ci": ci, "data": data}) 
    seaborn.timeseries._plot_ci_band(*args, **kwargs) 

seaborn.timeseries._plot_range_band = _plot_range_band 

cluster_overload = pd.read_csv("TSplot.csv", delim_whitespace=True) 
cluster_overload['Unit'] = cluster_overload.groupby(['Cluster','Week']).cumcount() 

ax = sns.tsplot(time='Week',value="Overload", condition="Cluster", unit="Unit", data=cluster_overload, 
       err_style="range_band", n_boot=0) 

uscita: enter image description here

Si noti che le regioni ombreggiate si allineano con il vero massimo e minimi nel grafico a linee!

Se si capisce perché è necessaria la variabile unit, per favore fatemelo sapere.


Se non li si vuole sullo stesso grafico, allora:

import pandas as pd 
import seaborn as sns 
import seaborn.timeseries 


def _plot_range_band(*args, central_data=None, ci=None, data=None, **kwargs): 
    upper = data.max(axis=0) 
    lower = data.min(axis=0) 
    #import pdb; pdb.set_trace() 
    ci = np.asarray((lower, upper)) 
    kwargs.update({"central_data": central_data, "ci": ci, "data": data}) 
    seaborn.timeseries._plot_ci_band(*args, **kwargs) 

seaborn.timeseries._plot_range_band = _plot_range_band 

cluster_overload = pd.read_csv("TSplot.csv", delim_whitespace=True) 
cluster_overload['subindex'] = cluster_overload.groupby(['Cluster','Week']).cumcount() 

def customPlot(*args,**kwargs): 
    df = kwargs.pop('data') 
    pivoted = df.pivot(index='subindex', columns='Week', values='Overload') 
    ax = sns.tsplot(pivoted.values, err_style="range_band", n_boot=0, color=kwargs['color']) 

g = sns.FacetGrid(cluster_overload, row="Cluster", sharey=False, hue='Cluster', aspect=3) 
g = g.map_dataframe(customPlot, 'Week', 'Overload','subindex') 

che produce il seguente, (si può giocare, ovviamente, con il rapporto di aspetto se si pensa le proporzioni sono spenti) enter image description here

+0

Grazie mille per il vostro aiuto, funziona perfettamente! Per quanto riguarda l'unità, creerò molte altre trame simili per il mio progetto attuale, e se capisco perché "unità" è obbligatoria, tornerò da te. –

+0

Penso che la seconda trama sia molto meglio. Ottimo lavoro. – Romain

+0

Grazie per l'aggiornamento! Spero che anche altri lo trovino utile. –

1

ho davvero pensato che sarei in grado di farlo con seaborn.tsplot. Ma non sembra proprio giusto. Ecco il risultato che ottengo con Seaborn:

cluster_overload = pd.read_csv("TSplot.csv", delim_whitespace=True) 
cluster_overload['Unit'] = cluster_overload.groupby(['Cluster','Week']).cumcount() 
ax = sns.tsplot(time='Week',value="Overload", condition="Cluster", ci=100, unit="Unit", data=cluster_overload) 

Uscite:

enter image description here

Sono molto confusa sul motivo per cui il parametro unit è necessaria in quanto la mia comprensione è che tutti i dati sono aggregati basa su (time, condition) Il Seaborn Documentation definisce unit come

Field in the data DataFrame identifying the sampling unit (e.g. subject, neuron, etc.). The error representation will collapse over units at each time/condition observation. This has no role when data is an array.

sono non certo del significato di "crollato", specialmente perché la mia definizione non lo renderebbe una variabile richiesta.

In ogni caso, ecco l'output se si desidera esattamente quello che hai discusso, non altrettanto bello. Non sono sicuro di come eseguire l'ombreggiamento manuale in quelle regioni, ma per favore condividi se lo capisci.

cluster_overload = pd.read_csv("TSplot.csv", delim_whitespace=True) 
grouped = cluster_overload.groupby(['Cluster','Week'],as_index=False) 
stats = grouped.agg(['min','mean','max']).unstack().T 
stats.index = stats.index.droplevel(0) 

colors = ['b','g','r'] 
ax = stats.loc['mean'].plot(color=colors, alpha=0.8, linewidth=3) 
stats.loc['max'].plot(ax=ax,color=colors,legend=False, alpha=0.3) 
stats.loc['min'].plot(ax=ax,color=colors,legend=False, alpha=0.3) 

Uscite: enter image description here

4

Ho finalmente utilizzato il buon vecchio plot con un disegno (sottotrame) che sembra (per me) più leggibile.

df = pd.read_csv('TSplot.csv', sep='\t', index_col=0) 
# Compute the min, mean and max (could also be other values) 
grouped = df.groupby(["Cluster", "Week"]).agg({'Overload': ['min', 'mean', 'max']}).unstack("Cluster") 

# Plot with sublot since it is more readable 
axes = grouped.loc[:,('Overload', 'mean')].plot(subplots=True) 

# Getting the color palette used 
palette = sns.color_palette() 

# Initializing an index to get each cluster and each color 
index = 0 
for ax in axes: 
    ax.fill_between(grouped.index, grouped.loc[:,('Overload', 'mean', index + 1)], 
        grouped.loc[:,('Overload', 'max', index + 1)], alpha=.2, color=palette[index]) 
    ax.fill_between(grouped.index, 
        grouped.loc[:,('Overload', 'min', index + 1)] , grouped.loc[:,('Overload', 'mean', index + 1)], alpha=.2, color=palette[index]) 
    index +=1 

enter image description here

+0

Grazie mille per questo, ne farò uno simile a questo, e consultarmi con il mio supervisore per vedere quale concordiamo. Domanda veloce a riguardo: per qualche ragione, quando si usa il DF memorizzato, non verrà eseguito. get KeyError: ('Overload', 'mean', 1). Tuttavia, se lo salvi in ​​csv, quindi reimportalo usando il parametro index_col = 0, funziona. Qualche idea sul perché questo sta accadendo? Grazie ancora. –

+0

Grazie per il tuo commento, sono sicuro che il tuo supervisore sarà dalla mia parte ;-). Dimmi ! Nessuna idea per il 'DataFrame' memorizzato in memoria poiché non riesco a riprodurre il problema. Non è correlato all'indice poiché l'esempio può essere eseguito senza 'index_col = 0'. Penso che dovresti controllare (stampare) 'DataFrame' memorizzato in memoria. – Romain

+0

Ho, più volte, entrambi utilizzando le istruzioni di stampa e in PyCharm. Mi manca decisamente qualcosa, ma riesco a malapena a dare un senso all'output di PyCharm https://gyazo.com/1a362bd8f2031f9bb88bed386888e7b6 (DF viene letto da CSV, DF1 è quello memorizzato dalla memoria). È molto strano però, come se lo salvassi, e lo carichi di nuovo (usando delim = ',' e col_index = 0 come params), funziona ... Tornerò da te domani sera per farti sapere quale grafico il mio supervisore pensato che fosse meglio! Grazie ancora per l'aiuto. –