Skip to content
Advertisement

How to make bar plot with varying widths and multiple values for each variable name in Python?

My question stems from the solution provided here.

In my code below, I would like to automatically take the list of variable names, x, and assign one colour for each variable from a colour map (e.g. using get_cmap). I would also only like each variable to appear once in the legend. In this example, the variables B & H have been duplicated, where I have assigned limegreen and black to them respectively.

import matplotlib.pyplot as plt

x = ["A","B","B","C","D","E","H","F","G","H"]

y = [-25, -10, -5, 5, 10, 30, 35, 40, 50, 60]

w = [30, 20, 30, 25, 40, 20, 40, 40, 40, 30]

colors = ["yellow","limegreen","limegreen","green","blue","red","black","brown","grey","black"]

plt.figure(figsize=(20,10))

xticks=[]
for n, c in enumerate(w):
    xticks.append(sum(w[:n]) + w[n]/2)
    
w_new = [i/max(w) for i in w]
a = plt.bar(xticks, height = y, width = w, color = colors, alpha = 0.8)
_ = plt.xticks(xticks, w)
plt.legend(a.patches, x)

Advertisement

Answer

Here, I am using dict and zip to get a single value of ‘x’, there are easier ways by importing additional libraries like numpy or pandas. What we are doing is custom building the matplotlib legend based on this article:

a = plt.bar(xticks, height = y, width = w, color = colors, alpha = 0.8)
_ = plt.xticks(xticks, w)
x, patches = zip(*dict(zip(x, a.patches)).items())
plt.legend(patches, x)

Output:

enter image description here

Details:

  1. Lineup x with a.patches using zip
  2. Assign each x as a key in dictionary with a patch, but dictionary keys are unique, so the patch for a x will be saved into the dictionary.
  3. Unpack the list of tuples for the items in the dictionary
  4. Use these as imports into plt.legend

Or you can use:

set_x = sorted(set(x))
xind = [x.index(i) for i in set_x]
set_patches = [a.patches[i] for i in xind]
plt.legend(set_patches, set_x)

Using a color map:

import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap

x = ["A","B","B","C","D","E","H","F","G","H"]

y = [-25, -10, -5, 5, 10, 30, 35, 40, 50, 60]

w = [30, 20, 30, 25, 40, 20, 40, 40, 40, 30]

col_map = plt.get_cmap('tab20')

plt.figure(figsize=(20,10))

xticks=[]
for n, c in enumerate(w):
    xticks.append(sum(w[:n]) + w[n]/2)
    
set_x = sorted(set(x))
xind = [x.index(i) for i in x]
colors = [col_map.colors[i] for i in xind]

w_new = [i/max(w) for i in w]
a = plt.bar(xticks, height = y, width = w, color = colors, alpha = 0.8)
_ = plt.xticks(xticks, w)

set_patches = [a.patches[i] for i in xind]

#x, patches = zip(*dict(zip(x, a.patches)).items())
plt.legend(set_patches, set_x)

Output:

enter image description here

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement