[FIXED] So erstellen Sie ein Diagramm mit gestapelten und beschrifteten Liniensegmenten

Ausgabe

Ich möchte eine Art gestapeltes Balkendiagramm erstellen [den richtigen Namen kenne ich nicht]. Ich habe die Grafik [für die Jahre 2016 und 2017] von Hand gezeichnet und hier angehängt.

Geben Sie hier die Bildbeschreibung ein

Der Code zum Erstellen des df ist unten:

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

data = [[2016.0, 0.4862, 0.4115, 0.3905, 0.3483, 0.1196],
 [2017.0, 0.4471, 0.4096, 0.3725, 0.2866, 0.1387],
 [2018.0, 0.4748, 0.4016, 0.3381, 0.2905, 0.2012],
 [2019.0, 0.4705, 0.4247, 0.3857, 0.3333, 0.2457],
 [2020.0, 0.4755, 0.4196, 0.3971, 0.3825, 0.2965]]

cols = ['attribute_time', '100-81 percentile', '80-61 percentile', '60-41 percentile', '40-21 percentile', '20-0 percentile']
df = pd.DataFrame(data, columns=cols)
#set seaborn plotting aesthetics
sns.set(style='white')
#create stacked bar chart
df.set_index('attribute_time').plot(kind='bar', stacked=True)

Die Daten müssen nicht übereinander gestapelt werden. Der Code erstellt ein gestapeltes Balkendiagramm, aber genau das muss nicht angezeigt werden. Das Perzentil muss beschriftete horizontale Linien haben, die das Perzentil auf der x-Achse für dieses Jahr angeben. Hat jemand Empfehlungen, wie man dieses Ziel erreichen kann? Handelt es sich um eine Art modifiziertes gestapeltes Balkendiagramm, das visualisiert werden muss?

Lösung

Mein Ansatz dazu besteht darin, die Daten als kategoriales Streudiagramm (Stripplot in Seaborn) darzustellen, wobei horizontale Linien anstelle von Punkten als Markierungen verwendet werden. Sie müssen einige Entscheidungen darüber treffen, wie und wo Sie die Dinge genau planen möchten, aber dies sollte Ihnen den Einstieg erleichtern!

Ich habe zunächst die Daten ein wenig modifiziert:

df['attribute_time'] = df['attribute_time'].astype('int') # Just to get rid of the decimals.

df = df.melt(id_vars = ['attribute_time'],
    value_name = 'pct_value',
    var_name = 'pct_range')

Das Schmelzen des DataFrame nimmt die breiten Daten und macht sie stattdessen lang, also sind die Spalten jetzt year, pct_value, und pct_rangeund es gibt eine Zeile für jeden Datenpunkt.

Als nächstes folgt das Plotten:

fig, ax = plt.subplots()

sns.stripplot(data = df,
    x = 'attribute_time',
    y = 'pct_value',
    hue = 'pct_range',
    jitter = False,
    marker = '_',
    s = 40,
    linewidth = 3,
    ax = ax)

Anstatt jeden Punkt mit dem Bereich zu beschriften, zu dem er gehört, dachte ich, es wäre viel sauberer, sie nach Farbe in Bereiche zu unterteilen.

Der jitterwird verwendet, wenn es viele Punkte für eine bestimmte Kategorie gibt, die sich überlappen könnten, um zu versuchen, sie daran zu hindern, sich zu berühren. In diesem Fall müssen wir uns darüber keine Gedanken machen, also habe ich den Jitter ausgeschaltet. Der markerStil wird hier als bezeichnet hline.

Der sParameter ist die horizontale Breite jeder Linie und das linewidthist die Dicke, sodass Sie ein wenig damit herumspielen können, um zu sehen, was für Sie am besten funktioniert.

Text wird der Abbildung mit der ax.textfolgenden Methode hinzugefügt:

for year, value in zip(df['attribute_time'],df['pct_value']):
    ax.text(year - 2016,
        value,
        str(value),
        ha = 'center',
        va = 'bottom',
        fontsize = 'small')

Die Abbildungskoordinaten sind trotz der horizontalen Jahresmarkierungen bei 0 beginnend indiziert, sodass die x-Position des Textes um das minimale Jahr (2016) nach links verschoben ist. Die y-Position ist gleich dem Wert, und der Text selbst ist eine Zeichenfolgendarstellung des Werts. Der Text wird über der Linie zentriert und sitzt leicht darüber, da sich der vertikale Anker unten befindet.
kategorisches Streudiagramm mit horizontalen Linienmarkierungen
Es gibt natürlich eine Menge, die Sie optimieren können, damit es mit Größe und Beschriftung und so aussieht, wie Sie es möchten, aber hoffentlich ist dies zumindest ein guter Anfang!


Beantwortet von –
Andrew


Antwort geprüft von –
Clifford M. (FixError Volunteer)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like