Search code examples
pythonpandasmatplotliblabelbar-chart

How to write two texts inside multiple bars in a horizontal bar graph matplotlib?


My code so far gives me something that looks like this:

Horizontal Bar plot sample

I am wanting to write in the bars themselves if possible to get something like this:

Desired Horizontal Bar plot

Here's my base code so far:


import pandas
import matplotlib.pyplot as plt
import numpy as np

df = pandas.DataFrame(dict(graph=['Fruits & Vegetables','Bakery'],
                           p=[round(0.942871692205*100,5), round(0.933348641475*100,5)],
                           q=[round(0.941649166881*100,5),round(0.931458324883*100,5)],
                           r=[round(0.940803376393*100,5),round(0.929429068047*100,5)],
                          ))

ind = np.arange(len(df))
width = 0.25

fig, ax = plt.subplots()
ax.barh(ind, df.p, width, color='red', label='Accrate>=80')
ax.barh(ind + width, df.q, width, color='green', label='Accrate>=79')
ax.barh(ind + 2*width, df.r, width, color='blue', label='Accrate>=78')
                           
ax.set(yticks=ind + 2*width, yticklabels=df.graph, ylim=[2*width - 1, len(df)])
ax.legend(bbox_to_anchor=(1.1, 1.05))

plt.show()

I'd like to put the number text as shown in the desired plot link! How do I do that?


Solution

  • I'm not sure what the logic of the number is, but with ax.text you can do something like this:

    i = 1 fig, ax = plt.subplots() colors = ['r','g','b'] labels = [80, 79, 78]

    for ii, col in enumerate('pqr'):
        bars = ax.barh(ind + width*ii, df[col], width, color=colors[ii], label=f'Accrate>={labels[ii]}')
        for bar in bars:
            (x,y), h, w = bar.get_xy(), bar.get_height(), bar.get_width()
    
            ax.text(x+5, y+h/2, str(i), color='w', weight='bold', va='center')
            ax.text(x+w-5, y+h/2, str(6+i), color='w', weight='bold', va='center', ha='right')
            i += 1
    

    Output:

    enter image description here