Currently migrating my blog from wordpress and other scattered sources.

Horizontal bar chart with 3 encodings

In this post I will describe how to create a chart with data encoded as glyphs and color from scratch. The chart below explains the gender difference in school performance in different states of India.

hbarchart

h_per =

State Boy Boy_count Girl Girl_count diff Boys_better
JH 38.0 971 35.0 956 3.0 True
BR 35.8 3550 37.0 4093 -1.2 False
UK 34.5 2438 33.0 2543 1.5 True
UP 44.0 3407 43.0 3757 1.0 True
KL 35.0 3346 40.0 3401 -5.0 False

Our aim is to encode data into

  • line : median values of boys and girls
  • colorbar : difference in median
  • circle size : count

Step 1

Plot lines on first axis ax.

fig, ax = plt.subplots(figsize = (5,5), dpi=75)

ax.barh(h_per.index ,width=h_per["Boy"], height=0.03, color="k", align="center", alpha =0.25, linewidth = 0)
ax.barh(h_per.index, width=-h_per["Girl"], height=0.03, color="k",align="center", alpha =0.25, linewidth = 0)

0

Step 2

Add scatter plot on to ax with marker size mapped on to count.

ax.scatter(x=h_per["Boy"], y=h_per.index, s=h_per["Boy_count"]*0.1, color="k", alpha=0.5)
ax.scatter(x=-h_per["Girl"], y=h_per.index, s=h_per["Girl_count"]*0.1, color = "k", alpha =0.5)

ax.set_xlim(-60, 60)
ax.set_xticklabels([str(abs(x)) for x in ax.get_xticks()]) # changing the x ticks to remove "-"
ax.set_xlabel("Median performance")

1

Step 3

Twin the axis ax to have an additional barchart on the same. This blog explains how to create _COLORS.

ax2 = ax.twiny()
ax2.barh(h_per.index, width=h_per["diff"], height=0.5, align="center", color=_COLORS)
ax2.set_xlim(-10, 10)
ax2.grid(False)
ax2.set_xlabel("Median performance difference (Boys - Girls)")

2

Step 4

Final touch; place legends, patches and labels on appropriate places.

# y-axis labels
ax.set_ylim(-1, len(h_per.index)+1)
ax.set_yticks(h_per.index)
ax.set_yticklabels(h_per['State'])
ax.axvline(x= 0, color='k', linewidth = 0.75, ymax = 0.8)

# legend
red_patch = mpatches.Patch(color='red', label='Boys Perform Better')
blue_patch = mpatches.Patch(color='blue', label='Girls Perform Better')
ax.legend(handles=[blue_patch, red_patch], loc=1, ncol=1)

# annotation patch
tboy = ax.text(50, -1.7, "Boys", ha="center", va="center", 
               rotation=0, size=10,color = "w", 
               bbox={"boxstyle":"rarrow,pad=0.3", "fc":"grey", "ec":"b", "lw":0})
tgirl = ax.text(-50, -1.7, "Girls", ha="center", va="center", 
                rotation=0, size=10,color = "w",
                bbox={"boxstyle":"larrow,pad=0.3", "fc":"grey", "ec":"b", "lw":0})

fig.savefig('3.png', dpi=75)

3