matplotlib advanced bar plot

I need to recreate a chart similar to the one below created in Excel. I was hoping to use matplotlib, but can’t seem to find any examples or reference for how to do a chart like this. I need to have bars colored based on a performance threshold, and also display the threshold. Can anyone point me in the right direction? I do need to be able to do this with Python, though.plot example

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

I gotta run, but here’s something to get you started:

import numpy as np
import matplotlib
matplotlib.rcParams['text.usetex'] = False
import matplotlib.pyplot as plt
import pandas

df = pandas.DataFrame(np.random.uniform(size=37)*100, columns=['A'])
threshold = 75
fig, ax = plt.subplots(figsize=(8,3))

good = df['A'][df['A'] >= threshold]
bad = df['A'][df['A'] < threshold]

ax.bar(left=good.index, height=good, align='center', color='ForestGreen', zorder=5)
ax.bar(left=bad.index, height=bad, align='center', color='Firebrick', zorder=5)

ax.axhline(y=threshold, linewidth=2, color='ForestGreen', zorder=0)

ax.set_xticks(df.index)
ax.set_xlim(left=df.index[0]-0.75, right=df.index[-1]+0.75)

def annotateBars(row, ax=ax):
    if row['A'] < 20:
        color = 'black'
        vertalign = 'bottom'
        vertpad = 2
    else:
        color = 'white'
        vertalign = 'top'
        vertpad = -2

    ax.text(row.name, row['A'] + vertpad, "{:.1f}%".format(row['A']),
            zorder=10, rotation=90, color=color,
            horizontalalignment='center',
            verticalalignment=vertalign,
            fontsize=8, weight='heavy')

junk = df.apply(annotateBars, ax=ax, axis=1)

And that gives me:
annotated bar plot

Method 2

This can now be plotted much more concisely:

  1. Axes.bar_label automatically labels bars (requires matplotlib 3.4.0+)
  2. Axes.bar has a color param that can accept an array of colors (e.g. via numpy.where)

So now it only takes a handful of lines, e.g. using Paul’s sample df = pd.DataFrame({'A': np.random.uniform(size=35) * 100}):

fig, ax = plt.subplots(figsize=(9, 3))
threshold = 75

# plot bars as blue if A > threshold, else red
color = np.where(df.A > threshold, 'blue', 'red')
ax.bar(x=df.index, height=df.A, color=color)

# add bar labels
ax.bar_label(ax.containers[0], fmt='%.1f%%')

# add threshold line
ax.axhline(threshold, alpha=0.5, zorder=0)

matplotlib advanced bar plot

Or for multiple thresholds, just update color as desired (e.g. via numpy.select):

upper, lower = 75, 25
color = np.select([df.A > upper, df.A < lower], ['blue', 'red'], default='gray')

matplotlib advanced bar plot

Note that a color array can also be passed into other bar plot helpers:


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x