Comment tracer plusieurs barres dans matplotlib, lorsque j'ai essayé d'appeler la fonction de barre plusieurs fois, elles se chevauchent et comme le montre la figure ci-dessous, la valeur rouge la plus élevée ne peut être vue que. Comment puis-je tracer les multiples barres avec des dates sur les axes des x?
Jusqu'à présent, j'ai essayé ceci:
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()
J'ai ceci:
Les résultats devraient être quelque chose comme, mais avec les dates sont sur les axes des x et les barres sont côte à côte:
python
matplotlib
John Smith
la source
la source
Réponses:
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()
Je ne sais pas ce que signifie "les valeurs y se chevauchent également", le code suivant résout-il votre problème?
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()
la source
autofmt_xdate()
, qui fait pivoter automatiquement les étiquettes.Le problème avec l'utilisation des dates comme valeurs x, c'est que si vous voulez un diagramme à barres comme dans votre deuxième image, ils vont être faux. Vous devez soit utiliser un graphique à barres empilées (les couleurs les unes sur les autres) ou grouper par date (une «fausse» date sur l'axe des x, regroupant simplement les points de données).
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()
la source
datetime64
: par exemple une valeur d' un mois:np.arange('2012-02', '2012-03', dtype='datetime64[D]')
. Vous devrez peut-être réfléchir davantage à la meilleure façon de représenter ces données si vous disposez de 40 ensembles de données (selon un autre commentaire) couvrant plus de 100 jours.xaxis_date
mais vous devrez adapter ce que j'ai écrit pour compenser vos valeurs de date (par exemple par un certain nombre d'heures d'utilisationtimedelta
) pour chaque série afin d'éviter qu'elles ne se chevauchent. L'autre réponse fait exactement cela, mais vous devrez peut-être vous débarrasser des étiquettes par la suite.Je sais qu'il s'agit de
matplotlib
, mais utiliserpandas
etseaborn
peut vous faire gagner beaucoup de temps: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()
la source
après avoir cherché une solution similaire et n'avoir rien trouvé d'assez flexible, j'ai décidé d'écrire ma propre fonction. Il vous permet d'avoir autant de barres par groupe que vous le souhaitez et de spécifier à la fois la largeur d'un groupe ainsi que les largeurs individuelles des barres au sein des groupes.
Prendre plaisir:
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()
Production:
la source
xticks
de l'intrigue, par exempleplt.xticks(range(5), ["one", "two", "three", "four", "five"])
J'ai fait cette solution: si vous voulez tracer plus d'une parcelle dans une figure, assurez-vous avant de tracer les prochaines parcelles que vous avez réglé le droit
matplotlib.pyplot.hold(True)
d'ajouter d'autres parcelles.Concernant les valeurs datetime sur l'axe X, une solution utilisant l'alignement des barres fonctionne pour moi. Lorsque vous créez un autre diagramme à barres avec
matplotlib.pyplot.bar()
, utilisez simplementalign='edge|center'
et définissezwidth='+|-distance'
.Lorsque vous définissez toutes les barres (tracés) à droite, vous verrez les barres bien.
la source
matplotlib.pyplot.hold
est obsolète depuis la v2.0, comme mentionné dans la documentation