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]:
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]:
Where I'm struggling is with the left and central sets of labels. The desired result is shown below, any help is appreciated.
CodePudding user response: