17

I want the negative bars to be facing downwards, and the positive upwards, with the x-axis(0-line) passing right between them. I tried this

chart = fig.bar(x, negative_data, width=35, color='r')
ax2 = plt.gca().twinx()
ax2.bar(x, positive_data, width=35, color='b')

But instead, I get merged red and white bars, both facing downwards. It seems that the arrays negative_data/positive_data only specify the height of the bar, but how do I specify the orientation? I need something to specify the coordinates of the tops of each bar.

Also, how do I make the widths be something reasonable, possibly dynamic as the graph is resized by user?

Here is an example of problematic widths:

x = [250, 1500, 2750, 4250, 6000, 8500, 13200]
negative_data = [0, 0, 0, 0, 0, 0, 0]
positive_data = [3, 0, 0, 0, 1, 0, 0]

How can I make the plot of those look nice?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Baron Yugovich
  • 3,843
  • 12
  • 48
  • 76

1 Answers1

40

You don't need to add a twin axis, you can plot both bar charts on the same axis like this:

x = range(7)
negative_data = [-1,-4,-3,-2,-6,-2,-8]
positive_data = [4,2,3,1,4,6,7,]

fig = plt.figure()
ax = plt.subplot(111)
ax.bar(x, negative_data, width=1, color='r')
ax.bar(x, positive_data, width=1, color='b')

bar chart with negative an positive y values

Bars with a width of one will fill the axes and will scale with the figure as it is resized.

Molly
  • 13,240
  • 4
  • 44
  • 45
  • Cool, works! Do you have any idea what I do about the widths though? – Baron Yugovich Aug 28 '14 at 14:31
  • 1
    What do you want the widths to look like? – Molly Aug 28 '14 at 14:39
  • Either the bars touching each other, or with a really small gap between them. Right now I get extremely thin vertical lines. They also look black, maybe because they are so thin, I cannot see the color. Thanks! – Baron Yugovich Aug 28 '14 at 14:46
  • That sounds like you have too many bars to be displayed in the figure. You might need s different type of plot or a larger figure. – Molly Aug 28 '14 at 15:01
  • But it only shows a couple bars, and they are all just vertical lines. I have 7 bars per plot. – Baron Yugovich Aug 28 '14 at 15:16
  • I updated my answer with a example of seven bars in a plot to show that it's possible. Without seeing your x an y data and the size of the axes I can't give you a better answer. – Molly Aug 28 '14 at 15:23
  • Cool. Can my problem have something to do with the fact that I have multiple subplots, and also within the same subplots, the bars can be of different orders of magnitude? But I don't know why the height difference can have to do with the width. – Baron Yugovich Aug 28 '14 at 15:27
  • Here is the problematic data: x = [250, 1500, 2750, 4250, 6000, 8500, 13200] negative_data = [0, 0, 0, 0, 0, 0, 0] positive_data = [3, 0, 0, 0, 1, 0, 0] How do I make this look nice? – Baron Yugovich Aug 28 '14 at 15:33
  • Try width = 1000. Then set the x and y limits of the axes. – Molly Aug 28 '14 at 15:41
  • Thanks, I will accept your answer. I have one more unrelated question: do you know how I can change the color of the frame of a subplot? – Baron Yugovich Aug 28 '14 at 16:13
  • Take a look [here](http://stackoverflow.com/questions/7778954/elegantly-changing-the-color-of-a-plot-frame-in-matplotlib) – Molly Aug 28 '14 at 16:48
  • is there no way to make this more automated? if you don't know which data is going to be positive or negative relative to the midline? – jimh Aug 15 '17 at 20:50