138 votes

Python matplotlib barres multiples

Comment tracer des barres multiples dans matplotlib, lorsque j'ai essayé d'appeler la fonction bar plusieurs fois, elles se chevauchent et comme on peut le voir sur la figure ci-dessous la valeur la plus élevée rouge peut être vue seulement. Comment puis-je tracer les barres multiples avec les dates sur les axes 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 eu ça :

enter image description here

Les résultats devraient ressembler à ceci, mais avec les dates sur les axes x et les barres les unes à côté des autres :

enter image description here

2voto

fr_andres Points 1420

J'ai modifié la solution de Pascscha en étendant l'interface, j'espère que cela aidera quelqu'un d'autre ! Caractéristiques principales :

  • Nombre variable d'entrées par groupe de barres
  • Couleurs personnalisables
  • Manipulation de x ticks
  • Étiquettes de barres entièrement personnalisables sur le dessus des barres

    def bar_plot(ax, data, group_stretch=0.8, bar_stretch=0.95,
    legend=True, x_labels=True, label_fontsize=8,
    colors=None, barlabel_offset=1,
    bar_labeler=lambda k, i, s: str(round(s, 3))):
    """
    Draws a bar plot with multiple bars per data point.
    param dict data: The data we want to plot, wher keys are the names of each bar group, and items is a list of bar values for the corresponding group.
    param float group_stretch: 1 means groups occupy the most (largest groups touch side to side if they have equal number of bars).
    param float bar_stretch: If 1, bars within a group will touch side to side.
    param bool x_labels: If true, x-axis will contain labels with the group names given at data, centered at the bar group.
    param int label_fontsize: Font size for the label on top of each bar.
    param float barlabel_offset: Distance, in y-values, between the top of the bar and its label.
    param function bar_labeler: If not None, must be a functor with signature f(group_name, i, scalar)->str, where each scalar is the entry found at data[group_name][i]. When given, returns a label to put on the top of each bar. Otherwise no labels on top of bars. """ sorted_data = list(sorted(data.items(), key=lambda elt: elt[0])) sorted_k, sorted_v = zip(*sorted_data) max_n_bars = max(len(v) for v in data.values()) group_centers = np.cumsum([max_nbars for in sorted_data]) - (max_n_bars / 2) bar_offset = (1 - bar_stretch) / 2 bars = defaultdict(list) # if colors is None: colors = {gname: [f"C{i}" for in values] for i, (g_name, values) in enumerate(data.items())} # for g_i, ((g_name, vals), g_center) in enumerate(zip(sorted_data, group_centers)): n_bars = len(vals) group_beg = g_center - (n_bars / 2) + (bar_stretch / 2) for val_i, val in enumerate(vals): bar = ax.bar(group_beg + val_i + bar_offset, height=val, width=bar_stretch, color=colors[g_name][val_i])[0] bars[g_name].append(bar) if bar_labeler is not None: x_pos = bar.get_x() + (bar.get_width() / 2.0) y_pos = val + barlabel_offset barlbl = bar_labeler(g_name, val_i, val) ax.text(x_pos, y_pos, barlbl, ha="center", va="bottom", fontsize=label_fontsize) if legend: ax.legend([bars[k][0] for k in sorted_k], sorted_k) # ax.set_xticks(group_centers) if x_labels: ax.set_xticklabels(sorted_k) else: ax.set_xticklabels() return bars, group_centers

Exemple d'exécution :

fig, ax = plt.subplots()
data = {"Foo": [1, 2, 3, 4], "Zap": [0.1, 0.2], "Quack": [6], "Bar": [1.1, 2.2, 3.3, 4.4, 5.5]}
bar_plot(ax, data, group_stretch=0.8, bar_stretch=0.95, legend=True,
         labels=True, label_fontsize=8, barlabel_offset=0.05,
         bar_labeler=lambda k, i, s: str(round(s, 3)))
fig.show()

enter image description here

1voto

Dave Points 77

J'ai trouvé cette solution : si vous voulez tracer plus d'un tracé dans une figure, assurez-vous avant de tracer les tracés suivants que vous avez défini les bons paramètres. matplotlib.pyplot.hold(True) pour pouvoir ajouter d'autres parcelles.

En ce qui concerne les valeurs de date 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() il suffit d'utiliser align='edge|center' et mettre width='+|-distance' .

Si vous réglez correctement toutes les barres (tracés), vous verrez bien les barres.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X