Display styling barh label with values ​​from dataframe

How can I display the values ​​for my stacked bar chart that come from the dataframe? How do I place labels above their respective sections on each bar and change the font so that it displays the same as it does on the grayscale chart?

This is related to this question , but it has a list of values ​​and not two lists inferred from a pandas dataframe. If it was a single list, I think I could pull the values ​​from one record in the dataframe, but with two lists, I'm not sure how to apply this to each row in the histogram.

My info frame:

Delin.  Group1  Group2  Group3  Group4  Group5
Census  0.2829  0.3387  0.2636  0.0795  0.0353
USPS    0.2538  0.3143  0.2901  0.1052  0.0366

      

My code:

import os
import pandas as pd
import time
#
start_time   = time.time()
#
output_dir   = r"C:\Some\Directory\For\Ouputs"
#
output_fig   = "race_barh2.png"
#
fig_path     = os.path.join(output_dir, output_fig)
#
os.chdir(output_dir)
#
input_csv    = r"C:\Some\Directory\To\My.csv"
#
df           = pd.read_csv(input_csv, delimiter = ",")
#
ax           = df.plot.barh( stacked = True, color = ("#252525", "#636363", "#969696", "#cccccc", "#f7f7f7"), edgecolor = "black", linewidth = 1)
#
ax.set_xlabel("Percentage of Total",  fontsize = 18)
#
ax.set_ylabel("Boundary Delineation", fontsize = 18)
#
ax.set_yticklabels(["Census", "USPS"])
#
ax.set_xticklabels(["0%", "20%", "40%", "60%", "80%", "100%"])
#
horiz_offset = 1.03
#
vert_offset  = 1
#
ax.legend(bbox_to_anchor=(horiz_offset, vert_offset))
#
fig          = ax.get_figure()
#
fig.savefig(fig_path, bbox_inches = "tight", dpi = 600)
#
#
#
end_time     = round( time.time() - start_time, 5 )
#
print "Seconds elapsed: {0}".format(end_time)

      

enter image description here

+1


source to share


1 answer


You can do it in the same way as in the mentioned question by annotating the bars. For a stacked bar chart, you need to iron the position of the labels a little to get them where you want them. You can play around with horizontalalignment

, verticalalignment

and add some margin like I did (+ 5).

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from cycler import cycler

#used gray colormap, you can use your own colors by replacing colormap='gray' with color=colors
colors = ["#252525", "#636363", "#969696", "#cccccc", "#f7f7f7"]
plt.rcParams['axes.prop_cycle'] = cycler(color=colors)

#dummy data
df = pd.DataFrame(np.random.randint(5, 8, (10, 3)), columns=['Group1', 'Group2', 'Group3'])

for col in df.columns.tolist():
    df[col] = df[col].apply(lambda x:x*100 / df[col].sum())

ax = df.T.plot.barh(stacked=True, colormap='gray', edgecolor='black', linewidth=1)

for lbl in ax.patches:
    ax.annotate("{:.0f}%".format(int(lbl.get_width())), (lbl.get_x(), lbl.get_y()+.5), verticalalignment='bottom', horizontalalignment='top', fontsize=8, color='black')

ax.legend(loc='center left', bbox_to_anchor=(1.0, .5))
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)

plt.show()

      



enter image description here

+2


source







All Articles