So zeichnen Sie mehrere Balken in matplotlib: Wenn ich mehrmals versuchte, die Balkenfunktion aufzurufen, überlappen sie sich, und wie in der folgenden Abbildung dargestellt, ist nur der höchste rote Wert zu sehen. Wie kann ich mehrere Balken mit Datumsangaben auf den x-Achsen zeichnen?
Bisher habe ich Folgendes versucht:
import matplotlib.pyplot as plt
import datetime
x = [
datetime.datetime(2011, 1, 4, 0, 0),
datetime.datetime(2011, 1, 5, 0, 0),
datetime.datetime(2011, 1, 6, 0, 0)
]
y = [4, 9, 2]
z = [1, 2, 3]
k = [11, 12, 13]
ax = plt.subplot(111)
ax.bar(x, y, width=0.5, color='b', align='center')
ax.bar(x, z, width=0.5, color='g', align='center')
ax.bar(x, k, width=0.5, color='r', align='center')
ax.xaxis_date()
plt.show()
Ich schaff das:
Die Ergebnisse sollten ungefähr so aussehen, aber die Daten befinden sich auf den x-Achsen und die Balken liegen nebeneinander:
python
matplotlib
John Smith
quelle
quelle
Antworten:
import matplotlib.pyplot as plt from matplotlib.dates import date2num import datetime x = [ datetime.datetime(2011, 1, 4, 0, 0), datetime.datetime(2011, 1, 5, 0, 0), datetime.datetime(2011, 1, 6, 0, 0) ] x = date2num(x) y = [4, 9, 2] z = [1, 2, 3] k = [11, 12, 13] ax = plt.subplot(111) ax.bar(x-0.2, y, width=0.2, color='b', align='center') ax.bar(x, z, width=0.2, color='g', align='center') ax.bar(x+0.2, k, width=0.2, color='r', align='center') ax.xaxis_date() plt.show()
Ich weiß nicht, was die "y-Werte überlappen sich auch" bedeutet. Löst der folgende Code Ihr Problem?
ax = plt.subplot(111) w = 0.3 ax.bar(x-w, y, width=w, color='b', align='center') ax.bar(x, z, width=w, color='g', align='center') ax.bar(x+w, k, width=w, color='r', align='center') ax.xaxis_date() ax.autoscale(tight=True) plt.show()
quelle
autofmt_xdate()
, wodurch die Beschriftungen automatisch gedreht werden.Das Problem bei der Verwendung von Datumsangaben als x-Werte besteht darin, dass sie falsch sind, wenn Sie ein Balkendiagramm wie in Ihrem zweiten Bild wünschen. Sie sollten entweder ein gestapeltes Balkendiagramm (Farben übereinander) oder eine Gruppierung nach Datum (ein "falsches" Datum auf der x-Achse, bei dem im Grunde nur die Datenpunkte gruppiert werden) verwenden.
import numpy as np import matplotlib.pyplot as plt N = 3 ind = np.arange(N) # the x locations for the groups width = 0.27 # the width of the bars fig = plt.figure() ax = fig.add_subplot(111) yvals = [4, 9, 2] rects1 = ax.bar(ind, yvals, width, color='r') zvals = [1,2,3] rects2 = ax.bar(ind+width, zvals, width, color='g') kvals = [11,12,13] rects3 = ax.bar(ind+width*2, kvals, width, color='b') ax.set_ylabel('Scores') ax.set_xticks(ind+width) ax.set_xticklabels( ('2011-Jan-4', '2011-Jan-5', '2011-Jan-6') ) ax.legend( (rects1[0], rects2[0], rects3[0]), ('y', 'z', 'k') ) def autolabel(rects): for rect in rects: h = rect.get_height() ax.text(rect.get_x()+rect.get_width()/2., 1.05*h, '%d'%int(h), ha='center', va='bottom') autolabel(rects1) autolabel(rects2) autolabel(rects3) plt.show()
quelle
datetime64
: zB Ein Monat wert :np.arange('2012-02', '2012-03', dtype='datetime64[D]')
. Wenn Sie über 40 Datensätze (gemäß einem anderen Kommentar) verfügen, die sich über 100 Tage erstrecken, müssen Sie möglicherweise genauer überlegen, wie diese Daten am besten dargestellt werden können.xaxis_date
aber Sie müssen das, was ich geschrieben habe, anpassen, um Ihre Datumswerte (z. B. um einige Stundentimedelta
) für jede Serie zu versetzen, damit sie sich nicht überschneiden. Die andere Antwort macht genau das, aber Sie müssen möglicherweise danach mit den Etiketten herumspielen.Ich weiß, dass es darum geht
matplotlib
, aber mitpandas
undseaborn
kann Ihnen viel Zeit sparen:df = pd.DataFrame(zip(x*3, ["y"]*3+["z"]*3+["k"]*3, y+z+k), columns=["time", "kind", "data"]) plt.figure(figsize=(10, 6)) sns.barplot(x="time", hue="kind", y="data", data=df) plt.show()
quelle
Nachdem ich nach einer ähnlichen Lösung gesucht und nichts gefunden hatte, das flexibel genug war, beschloss ich, meine eigene Funktion dafür zu schreiben. Sie können so viele Balken pro Gruppe haben, wie Sie möchten, und sowohl die Breite einer Gruppe als auch die einzelnen Breiten der Balken innerhalb der Gruppen angeben.
Genießen:
from matplotlib import pyplot as plt def bar_plot(ax, data, colors=None, total_width=0.8, single_width=1, legend=True): """Draws a bar plot with multiple bars per data point. Parameters ---------- ax : matplotlib.pyplot.axis The axis we want to draw our plot on. data: dictionary A dictionary containing the data we want to plot. Keys are the names of the data, the items is a list of the values. Example: data = { "x":[1,2,3], "y":[1,2,3], "z":[1,2,3], } colors : array-like, optional A list of colors which are used for the bars. If None, the colors will be the standard matplotlib color cyle. (default: None) total_width : float, optional, default: 0.8 The width of a bar group. 0.8 means that 80% of the x-axis is covered by bars and 20% will be spaces between the bars. single_width: float, optional, default: 1 The relative width of a single bar within a group. 1 means the bars will touch eachother within a group, values less than 1 will make these bars thinner. legend: bool, optional, default: True If this is set to true, a legend will be added to the axis. """ # Check if colors where provided, otherwhise use the default color cycle if colors is None: colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] # Number of bars per group n_bars = len(data) # The width of a single bar bar_width = total_width / n_bars # List containing handles for the drawn bars, used for the legend bars = [] # Iterate over all data for i, (name, values) in enumerate(data.items()): # The offset in x direction of that bar x_offset = (i - n_bars / 2) * bar_width + bar_width / 2 # Draw a bar for every value of that type for x, y in enumerate(values): bar = ax.bar(x + x_offset, y, width=bar_width * single_width, color=colors[i % len(colors)]) # Add a handle to the last drawn bar, which we'll need for the legend bars.append(bar[0]) # Draw legend if we need if legend: ax.legend(bars, data.keys()) if __name__ == "__main__": # Usage example: data = { "a": [1, 2, 3, 2, 1], "b": [2, 3, 4, 3, 1], "c": [3, 2, 1, 4, 2], "d": [5, 9, 2, 1, 8], "e": [1, 3, 2, 2, 3], "f": [4, 3, 1, 1, 4], } fig, ax = plt.subplots() bar_plot(ax, data, total_width=.8, single_width=.9) plt.show()
Ausgabe:
quelle
xticks
Handlung, zBplt.xticks(range(5), ["one", "two", "three", "four", "five"])
Ich habe diese Lösung gewählt: Wenn Sie mehr als ein Diagramm in einer Figur zeichnen möchten, stellen Sie sicher, dass Sie vor dem Zeichnen der nächsten Diagramme, die Sie richtig eingestellt haben,
matplotlib.pyplot.hold(True)
weitere Diagramme hinzufügen können.In Bezug auf die Datums- / Uhrzeitwerte auf der X-Achse funktioniert für mich eine Lösung mit der Ausrichtung von Balken. Wenn Sie ein anderes Balkendiagramm mit erstellen
matplotlib.pyplot.bar()
, verwenden Sie es einfachalign='edge|center'
und legen Sie es festwidth='+|-distance'
.Wenn Sie alle Balken (Diagramme) richtig eingestellt haben, werden die Balken gut angezeigt.
quelle
matplotlib.pyplot.hold
als wäre es seit Version 2.0 veraltet, wie in den Dokumenten erwähnt