Home > database >  Matplotlib - Creating a Stacked barh with x axis labels positioned centrally and value labels positi
Matplotlib - Creating a Stacked barh with x axis labels positioned centrally and value labels positi

Time:09-22

I'm looking to create a barh plot where the index appears as a label in the center of the row and the values appear on the inside edges of the chart, essentially replicating Excel's 'inside end' and 'inside base' label positions

The following is a simple example to illustrate the problem and desired result:

In [1]:
# Setting up a normalised data frame:

data = {"Names": ["Amy", "Bob", "Chris"],
   "Scores1": [70, 81, 23], 
   "Scores2": [30, 100, 63]}
df = pd.DataFrame(data).set_index("Names")
df_norm = df.div(df.sum(axis = 1), axis = 0)
df_norm

Out [1]:
        Scores1 Scores2
Names       
Amy       0.70  0.30
Bob       0.45  0.55
Chris     0.27  0.73


In [2]:
# Plotting stacked barh and tidying up the asthetics

ax = df_Norm.plot.barh(stacked = True, width = 0.85, color = ['r', 'orange'])
plt.legend(
    bbox_to_anchor = (0.5, -0.1),
    loc = "lower center",
    borderaxespad = 0,
    frameon = False,
    ncol = 2
)

plt.xlim(0.05, 1)
ax.axis('off')

# 'Drawing' the required labels note that the index labels need to appear twice and overlap
# with alpha = 0.5 in the event that one of the bars does not exist e.g Scores1 = 0

plt.bar_label(ax.containers[0], label_type = 'edge', labels = data["Scores1"])
plt.bar_label(Ax.containers[0], label_type = 'center', labels = data["Names"], alpha = 0.5)
plt.bar_label(ax.containers[1], label_type = 'center', labels = data["Names"], alpha = 0.5)
plt.bar_label(ax.containers[1], label_type = 'edge', labels = data["Scores2"])

Out [2]:

enter image description here

Getting the right side labels is a simple task as the padding required to do so is constant, I found that k = -20 works for up to 3 digit numbers.

So changing the last line above to include a constant padding results in the following

In [3]: 
k = -20
plt.bar_label(ax.containers[1], label_type = 'edge', labels = data["Scores2"], padding = k)

Out [3]:

enter image description here

Where I'm struggling is with the left and central sets of labels. The desired result is shown below, any help is appreciated.

enter image description here

CodePudding user response:

You can use plot

  • Related