0

This simple example of a Stacked Bar Graph from the matplotlib website demonstrates exactly what I'm trying to do. However, the data I'm using is dynamic and often contains zero values. However, when I plot zero values, they display on the graph as a small, thin line. Following the advice from some other posts, I replaced the zero values with numpy.nan values. However, this produced a new problem: the stacked bars do not display if one of the bars on that x-value is numpy.nan.

I'm using matplotlib with the Qt5Agg backend because I'm embedding matplotlib plots in my PyQt5 application. However, I don't think this has anything to do with the issue because it is reproducible in the following examples.

This is a simplified example from the website: (1) Stacked Bars with Non-NaN Data, and was produced from the following:

import numpy as np
import matplotlib
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt

menMeans = (10, 35, 30, 35, 27)
womenMeans = (20, 32, 34, 20, 25)
ind = np.arange(5)
width = 0.35

p1 = plt.bar(ind, menMeans, width)
p2 = plt.bar(ind, womenMeans, width, bottom=menMeans)

plt.ylabel('Scores')
plt.title('Scores by group and gender')
plt.xticks(ind, ('G1', 'G2', 'G3', 'G4', 'G5'))
plt.yticks(np.arange(0, 81, 10))
plt.legend((p1[0], p2[0]), ('Men', 'Women'))
plt.axes().set_ylim(0, 80)

plt.show()

(2) This example is what I'm having problems with. It was produced by the following:

import numpy as np
import matplotlib
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt

menMeans = (np.nan, 35, 30, 35, 27)                                  # NAN VALUE WAS ADDED
womenMeans = (20, 32, 34, 20, 25)
ind = np.arange(5)
width = 0.35

p1 = plt.bar(ind, menMeans, width)
p2 = plt.bar(ind, womenMeans, width, bottom=menMeans)

plt.ylabel('Scores')
plt.title('Scores by group and gender')
plt.xticks(ind, ('G1', 'G2', 'G3', 'G4', 'G5'))
plt.yticks(np.arange(0, 81, 10))
plt.legend((p1[0], p2[0]), ('Men', 'Women'))
plt.axes().set_ylim(0, 80)

plt.show()

The question: How does one deal with plotting zero-values/numpy.nan values on a stacked bar graph in matplotlib? The behavior I want is the following: zero-value bars should not be displayed, but should still allow the other bars on top of it to be displayed.

This is my first post. Apologies if I've made any mistakes. I've tried to follow the rules exactly.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241

1 Answers1

1

use numpy's nan_to_num() to replace NaN by zeroes in your bottom= argument:

menMeans = (np.nan, 35, 30, 35, 27)                                  # NAN VALUE WAS ADDED
womenMeans = (20, 32, 34, 20, 25)
ind = np.arange(5)
width = 0.35

p1 = plt.bar(ind, menMeans, width)
p2 = plt.bar(ind, womenMeans, width, bottom=np.nan_to_num(menMeans))  # no more NaNs in bottom=

plt.ylabel('Scores')
plt.title('Scores by group and gender')
plt.xticks(ind, ('G1', 'G2', 'G3', 'G4', 'G5'))
plt.yticks(np.arange(0, 81, 10))
plt.legend((p1[0], p2[0]), ('Men', 'Women'))
plt.ylim((0,80))

plt.show()

PS: if you're using the pyplot approach (see difference between pyplot and object-oriented APIs), you should be calling plt.ylim(), instead of what you were doing

Diziet Asahi
  • 38,379
  • 7
  • 60
  • 75
  • You are a life saver! Thank you so much! I can't believe the answer was so simple. I appreciate the quick response! – Kayvon Khosrowpour Jul 27 '18 at 14:31
  • @KayvonKhosrowpour If this answer solved your problem, please [consider accepting it.](https://stackoverflow.com/help/accepted-answer) – Mr. T Jul 27 '18 at 17:54