Come posso tracciare Pandas DataFrame separati come sottotrame?


129

Ho alcuni Pandas DataFrame che condividono la stessa scala di valori, ma con colonne e indici diversi. Quando invoco df.plot(), ottengo immagini di trama separate. quello che voglio veramente è averli tutti nella stessa trama delle sottotrame, ma sfortunatamente non riesco a trovare una soluzione a come e apprezzerei molto un aiuto.

Risposte:


252

È possibile creare manualmente le sottotrame con matplotlib, quindi tracciare i dataframe su una sottotrama specifica utilizzando la axparola chiave. Ad esempio per 4 sottotrame (2x2):

import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=2, ncols=2)

df1.plot(ax=axes[0,0])
df2.plot(ax=axes[0,1])
...

Ecco axesun array che contiene i diversi assi della sottotrama e puoi accedervi semplicemente indicizzando axes.
Se desideri un asse x condiviso, puoi fornire sharex=Truea plt.subplots.


33
Nota che, fastidiosamente, .subplots()restituisce diversi sistemi di coordinate a seconda delle dimensioni della matrice di sottotrame che stai creando. Quindi, se restituisci sottotrame in cui, ad esempio, nrows=2, ncols=1dovrai indicizzare gli assi come axes[0]e axes[1]. Vedere stackoverflow.com/a/21967899/1569221
— canary_in_the_data_mine

3
@canary_in_the_data_mine Grazie, è davvero fastidioso ... il tuo commento mi ha salvato un po 'di tempo :) non riuscivo a capire perché stavo ricevendoIndexError: too many indices for array
— snd

9
@canary_in_the_data_mine Questo è fastidioso solo se .subplot()vengono utilizzati gli argomenti predefiniti per . Impostare squeeze=Falseper forzare la .subplot()restituzione sempre di un ndarrayin ogni caso di righe e colonne.
— Martin,

73

Puoi vedere ad es. nella documentazione che mostra la risposta di joris. Sempre dalla documentazione, potresti anche impostare subplots=Truee layout=(,)all'interno della plotfunzione panda :

df.plot(subplots=True, layout=(1,2))

Puoi anche usare fig.add_subplot()che accetta parametri della griglia di sottotrama come 221, 222, 223, 224, ecc. Come descritto nel post qui . Simpatici esempi di trama su frame di dati panda, comprese le sottotrame, possono essere visti in questo notebook ipython .


2
sebbene la risposta di joris sia ottima per l'utilizzo generale di matplotlib, questo è eccellente per chiunque desideri utilizzare i panda per una rapida visualizzazione dei dati. Inoltre si adatta un po 'meglio alla domanda.
— Little Bobby Tables

Tieni presente che subplotse layoutkwargs genereranno più grafici SOLO per un singolo dataframe. Questo è correlato, ma non una soluzione, alla questione di OP di tracciare più dataframe in un unico grafico.
— Austin A

1
Questa è la risposta migliore per l'uso puro dei Panda. Ciò non richiede l'importazione diretta di matplotlib (anche se normalmente dovresti comunque) e non richiede il ciclo per forme arbitrarie (puoi usare layout=(df.shape[1], 1), ad esempio).
— Anatoly Makarevich

20

Puoi usare il familiare stile Matplotlib chiamando un figuree subplot, ma devi semplicemente specificare l'asse corrente usando plt.gca(). Un esempio:

plt.figure(1)
plt.subplot(2,2,1)
df.A.plot() #no need to specify for first axis
plt.subplot(2,2,2)
df.B.plot(ax=plt.gca())
plt.subplot(2,2,3)
df.C.plot(ax=plt.gca())

eccetera...


7

È possibile tracciare più sottotrame di più frame di dati panda utilizzando matplotlib con un semplice trucco di creare un elenco di tutti i frame di dati. Quindi utilizzare il ciclo for per tracciare sottotrame.

Codice di lavoro:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# dataframe sample data
df1 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
df2 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
df3 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
df4 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
df5 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
df6 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
#define number of rows and columns for subplots
nrow=3
ncol=2
# make a list of all dataframes 
df_list = [df1 ,df2, df3, df4, df5, df6]
fig, axes = plt.subplots(nrow, ncol)
# plot counter
count=0
for r in range(nrow):
    for c in range(ncol):
        df_list[count].plot(ax=axes[r,c])
        count=+1

inserisci qui la descrizione dell'immagine

Usando questo codice puoi tracciare sottotrame in qualsiasi configurazione. Devi solo definire il numero di righe nrowe il numero di colonne ncol. Inoltre, è necessario creare un elenco di frame di dati df_listche si desidera tracciare.


2
presta attenzione all'errore di battitura nell'ultima riga: non è count =+1macount +=1
— PEBKAC

4

Puoi usare questo:

fig = plt.figure()
ax = fig.add_subplot(221)
plt.plot(x,y)

ax = fig.add_subplot(222)
plt.plot(x,z)
...

plt.show()

3

Potrebbe non essere necessario utilizzare i Panda. Ecco un grafico matplotlib delle frequenze dei gatti:

inserisci qui la descrizione dell'immagine

x = np.linspace(0, 2*np.pi, 400)
y = np.sin(x**2)

f, axes = plt.subplots(2, 1)
for c, i in enumerate(axes):
  axes[c].plot(x, y)
  axes[c].set_title('cats')
plt.tight_layout()

1

Basandosi sulla risposta @joris sopra, se hai già stabilito un riferimento alla sottotrama, puoi usare anche il riferimento. Per esempio,

ax1 = plt.subplot2grid((50,100), (0, 0), colspan=20, rowspan=10)
...

df.plot.barh(ax=ax1, stacked=True)

0

Come creare più grafici da un dizionario di dataframe con dati lunghi (ordinati)

  • ipotesi

    • C'è un dizionario di più dataframe di dati ordinati
      • Creato leggendo da file
      • Creato separando un singolo dataframe in più dataframe
    • Le categorie cat,, possono essere sovrapposte, ma tutti i dataframe potrebbero non contenere tutti i valori dicat
    • hue='cat'
  • Poiché i dataframe vengono iterati, non è garantito che i colori vengano mappati allo stesso modo per ogni grafico

    • È necessario creare una mappa dei colori personalizzata dai 'cat'valori univoci per tutti i dataframe
    • Poiché i colori saranno gli stessi, posiziona una legenda a lato delle trame, invece di una legenda in ogni trama

Importazioni e dati sintetici

import pandas as pd
import numpy as np  # used for random data
import random  # used for random data
import matplotlib.pyplot as plt
from matplotlib.patches import Patch  # for custom legend
import seaborn as sns
import math import ceil  # determine correct number of subplot


# synthetic data
df_dict = dict()
for i in range(1, 7):
    np.random.seed(i)
    random.seed(i)
    data_length = 100
    data = {'cat': [random.choice(['A', 'B', 'C']) for _ in range(data_length)],
            'x': np.random.rand(data_length),
            'y': np.random.rand(data_length)}
    df_dict[i] = pd.DataFrame(data)


# display(df_dict[1].head())

  cat         x         y
0   A  0.417022  0.326645
1   C  0.720324  0.527058
2   A  0.000114  0.885942
3   B  0.302333  0.357270
4   A  0.146756  0.908535

Crea mappature di colore e trama

# create color mapping based on all unique values of cat
unique_cat = {cat for v in df_dict.values() for cat in v.cat.unique()}  # get unique cats
colors = sns.color_palette('husl', n_colors=len(unique_cat))  # get a number of colors
cmap = dict(zip(unique_cat, colors))  # zip values to colors

# iterate through dictionary and plot
col_nums = 3  # how many plots per row
row_nums = math.ceil(len(df_dict) / col_nums)  # how many rows of plots
plt.figure(figsize=(10, 5))  # change the figure size as needed
for i, (k, v) in enumerate(df_dict.items(), 1):
    plt.subplot(row_nums, col_nums, i)  # create subplots
    p = sns.scatterplot(data=v, x='x', y='y', hue='cat', palette=cmap)
    p.legend_.remove()  # remove the individual plot legends
    plt.title(f'DataFrame: {k}')

plt.tight_layout()
# create legend from cmap
patches = [Patch(color=v, label=k) for k, v in cmap.items()]
# place legend outside of plot; change the right bbox value to move the legend up or down
plt.legend(handles=patches, bbox_to_anchor=(1.06, 1.2), loc='center left', borderaxespad=0)
plt.show()

inserisci qui la descrizione dell'immagine

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.