Matplotlib.pyplot: Mehrere Graphen in jedem Subplot anzeigen

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
pytony
User
Beiträge: 25
Registriert: Mittwoch 14. Juni 2017, 11:26

Liebe Python-Programmierer!

Ich habe eine Frage bezueglich matplotlib, aber zuerst schreibe ich, was mein Ziel ist.

Ich habe mehrere Zeitreihen von verschiedenen Bankinstituten aus verschiedenen Laendern, die die selben Balance Sheet Positionen haben. Bspw. 1.1, 1.2., 1.3, 2.1, 2.2., 2.3.,...,9.1.

Nun soll jedes Subplot eine Position ('check_num') behandeln und folgendes beinhalten:

- die Zeitreihe der betroffenen Position jeder Bank als grauen Graphen darstellen (specific bank)
- die Zeitreihe aller Banken (also Durchschnitt aller Banken) bzgl. einer bestimmten Position als orangenen Graphen darstellen (all banks)
- das ganze als 22x1 Subplots (oder 11x2 Subplots anzeigen)
- jedes Subplot...
...........hat eine Ueberschrift, die angibt, um welche Position es sich gerade handelt
...........hat eine eigene x- und y-Achsenbeschriftung (x, die einzelnen Quartale 'Date': y, die Werte 'Differenz')


Somit haette man fuer jede Position eine Art Benchmark (der Durchschnitt) und der Vergleich dazu von den anderen Banken.

Nun habe ich folgenden Code in jupyternotebooks geschrieben, der mir leider komisches ausgibt: Zwei uebereinander liegende Graphen, wo das erste figure nichts beinhaltet und das zweite figure alle Graphen einer bestimmten Position zusammengepresst. Und zwar so, dass man nichts erkennt:

Code: Alles auswählen

%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd


banks_sep_by_countries_graph = pd.read_excel('banks_sep_by_countries.xlsx').fillna(method='ffill').copy(deep=True)
banks_sep_by_countries_graph["period_as_date"] = pd.to_datetime(banks_sep_by_countries_graph["period_as_date"]).dt.to_period('Q')
all_banks_graph = pd.read_excel('all_banks.xlsx').fillna(method='ffill').copy(deep=True)
all_banks_graph["period_as_date"] = pd.to_datetime(all_banks_graph["period_as_date"]).dt.to_period('Q')

plt.style.use('seaborn-darkgrid')
my_dpi=96
plt.figure(figsize=(480/my_dpi, 480/my_dpi), dpi=my_dpi)

y = 1
x = int(len(list(all_banks_graph['check_num'].drop_duplicates())))
plots_total = int(x*y)

plt.suptitle("Data Quality over Time")
plt.tight_layout()
fig, axs = plt.subplots(x, y)
x_ticks = np.arange(0,len(list(specific_country_dataframe['period_as_date'].drop_duplicates()))-1,1)
for i in range(0, x):
    for check_num in list(all_banks_graph['check_num'].drop_duplicates()):
        
        check_num_dataframe = all_banks_graph.loc[all_banks_graph['check_num'] == check_num]
        axs[i].plot(x=x_ticks,y=check_num_dataframe['perc_difference'], marker='', color='orange', linewidth=4, alpha=0.7)
        
        for country in list(banks_sep_by_countries_graph['group_area'].drop_duplicates()):
            
            specific_country_dataframe = banks_sep_by_countries_graph.loc[(banks_sep_by_countries_graph['group_area'] == country) & (banks_sep_by_countries_graph['check_num'] == check_num)]
            axs[i].plot(x=x_ticks,y=specific_country_dataframe['perc_difference'], marker='', color='grey', linewidth=1, alpha=0.4)
        
        axs[i].set_xlabel('Date')
        axs[i].set_ylabel('Difference (%)')
        axs[i].set_title(f"{check_num}", loc='center', fontsize=12, fontweight=0, color='orange')
        axs[i].set_xticks(x_ticks)
        axs[i].set_xticklabels(specific_country_dataframe['period_as_date'])

Damit ihr euch das ganze anschauen koennt und das Problem reproduzieren koennt, findet ihr unter diesen Link die Daten archiviert als zip: https://1drv.ms/u/s!As0cHBpV4ab_61fIOg_ ... 8?e=Z2ghtC


Ich bedanke mich fuer eure Hilfe im Voraus :) Ich bin in Sachen matplotlib noch neu :oops:

viele gruesse,
pytony
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Das Skript läuft nicht, da `specific_country_dataframe` nicht definiert ist, bzw. dass das wohl noch von einem vorhergehenden Lauf definiert war. Das ist das Problem an diesen Notebooks, dass sie einen internen Zustand haben, der Ergebnisse zufällig erscheinen lassen.

Gerade frisch geladene Daten zu kopieren und die eine Kopie wegzuschmeißen, macht die Kopie überflüssig. Was soll das my bei `my_dpi`? Gibt es auch ein `your_dpi`?

x und y stehen normalerweise für Kommazahlen, nicht für Ganzzahlen, besser wäre hier sowieso etwas wie row_count und column_count.

Mit `figure` machst Du einen ersten Plot und mit `subplots` einen zweiten, der erste bleibt aber leer.

Problematisch ist dann die doppelte for-Schleife, denn da willst Du nur eine Schleife über i und check_nums gemeinsam. Statt aber drop_duplicates und Vergleiche zu benutzen, nimm groupby.

Was Du dann tatsächlich plotten willst, verstehe ich nicht.

Ich komm dann auf ungefähr das:

Code: Alles auswählen

banks_sep_by_countries_graph = pd.read_excel('uiui/banks_sep_by_countries.xlsx').fillna(method='ffill')
banks_sep_by_countries_graph["period_as_date"] = pd.to_datetime(banks_sep_by_countries_graph["period_as_date"]).dt.to_period('Q')
all_banks_graph = pd.read_excel('uiui/all_banks.xlsx').fillna(method='ffill')
all_banks_graph["period_as_date"] = pd.to_datetime(all_banks_graph["period_as_date"]).dt.to_period('Q')

plt.style.use('seaborn-darkgrid')
dpi = 96
plt.figure(figsize=(480/dpi, 480/dpi), dpi=dpi)

bank_groups = all_banks_graph.groupby(by='check_num')
banks_sep_by_countries = banks_sep_by_countries_graph.groupby(by='check_num')
fig, axis = plt.subplots(len(bank_groups), 1)
fig.suptitle("Data Quality over Time")
fig.tight_layout()
for axes, (check_num, banks) in zip(axis, bank_groups):
    axes.plot(banks['perc_difference'], marker='', color='orange', linewidth=4, alpha=0.7)
    for area, banks_by_area in banks_sep_by_countries.get_group(check_num).groupby(by='group_area'):
        axes.plot(banks_by_area['perc_difference'], marker='', color='grey', linewidth=1, alpha=0.4)
    axes.set_xlabel('Date')
    axes.set_ylabel('Difference (%)')
    axes.set_title(f"{check_num}", loc='center', fontsize=12, fontweight=0, color='orange')
pytony
User
Beiträge: 25
Registriert: Mittwoch 14. Juni 2017, 11:26

hallo sirius!

vielen lieben Dank fuer deine Hilfe.


Sirius3 hat geschrieben: Montag 21. Oktober 2019, 20:22Was soll das my bei `my_dpi`? Gibt es auch ein `your_dpi`?
Habe einen Anhaltspunkt gebraucht und deswegen mit https://python-graph-gallery.com/123-hi ... line-plot/ erstmal angefangen.
Sirius3 hat geschrieben: Montag 21. Oktober 2019, 20:22Mit `figure` machst Du einen ersten Plot und mit `subplots` einen zweiten, der erste bleibt aber leer.
ok...erstes Problem geloest :)
Sirius3 hat geschrieben: Montag 21. Oktober 2019, 20:22Was Du dann tatsächlich plotten willst, verstehe ich nicht.
Mein Ziel ist, fuer jede Check_num ein Subplot zu erstellen. Jede Check_num stellt eine Position der Bank dar. Ich habe nun vor fuer jede Position jeder Bank ein eigenes Subplot zu erstellen. Zusaetzlich wird ein weiteres Plot zu jedem Subplot hinzugefuegt , was den Durchschnitt aller Banken darstellen soll und zwar in Orange.

So sehe ich wie die jeweilige Position in jeder Bank im Vergleich zum Durchschnit aller Banken abschneidet.




Ich arbeite mich jetzt durch deinen Vorschlag durch und melde mich wieder :)
Zuletzt geändert von pytony am Montag 21. Oktober 2019, 21:31, insgesamt 1-mal geändert.
pytony
User
Beiträge: 25
Registriert: Mittwoch 14. Juni 2017, 11:26

UPDATE: Also ich habe es jetzt nach deinem Vorschlag geaendert, aber es erscheinen keine Graphiken. Das ist sehr komisch...
Antworten