Matplotlib: Histogram with bars inside grid lines...how??

E

Enigma Curry

I'm playing around with matplotlib for the first time. I'm trying to
make a very simple histogram of values 1-6 and how many times they
occur in a sequence. However, after about an hour of searching I cannot
make the histogram stay within the bounds of the grid lines.

Here is my example:

pylab.grid()
x_values=[1,1,2,2,2,3,3,3,4,4,4,5,5,6,6,6]
pylab.hist(x_values,6)
pylab.show()

This produced the following image:
http://enigmacurry.com/usenet/historgram-bars-not-in-grid-lines.png

Starting with bar number 2, it creeps into grid 1.. and finally with
bar number 5 it's almost entirely in grid 4.. how do I make the bars
stay in their own grid lines?

I can see that hist() is somehow derived from bar() ... so it appears
that hist() has some undocumented parameters. I tried specifiying
width=1 but that just squished all of the bars together.

Also, is there a more object-oriented graphing package for Python? (How
am I supposed to know that hist() is derived from bar() if the docs
don't show proper inheritance?)

Thanks!
 
E

Enigma Curry

Two things:

1) I now see where width is defined in the hist() documentation... I
was expecting it to be in the definition up at the top, but instead the
definition has **kwords.. not very helpful.

2) I noticed in my original historgram, that the y scale was not the
same as the x scale.. so I updated my code:

import pylab

pylab.grid()
x_values=[1,1,2,2,2,3,3,3,4,4,4,5,5,6,6,6]
pylab.hist(x_values,6)
pylab.yticks(pylab.arange(3))
pylab.axis('scaled')
pylab.show()


It produced this image:
http://enigmacurry.com/usenet/historgram-bars-not-in-grid-lines2.png

It has the same problem..
 
J

John Hunter

Enigma> I'm playing around with matplotlib for the first time. I'm
Enigma> trying to make a very simple histogram of values 1-6 and
Enigma> how many times they occur in a sequence. However, after
Enigma> about an hour of searching I cannot make the histogram
Enigma> stay within the bounds of the grid lines.

Enigma> Here is my example:

Enigma> pylab.grid() x_values=[1,1,2,2,2,3,3,3,4,4,4,5,5,6,6,6]
Enigma> pylab.hist(x_values,6) pylab.show()

Enigma> This produced the following image:
Enigma> http://enigmacurry.com/usenet/historgram-bars-not-in-grid-lines.png

Enigma> Starting with bar number 2, it creeps into grid 1.. and
Enigma> finally with bar number 5 it's almost entirely in grid
Enigma> 4.. how do I make the bars stay in their own grid lines?

While exactly what you want is something of an enigma to me, I can
offer some advice and terminology. The bars of hist make no attempt
to stay within the bounds of the grid lines... The bars have as their
left most boundary the bins you choose for the histogram. As a first
step, I suggest setting these bins explicitly, rather than letting the
hist command choose them automatically

from pylab import hist, xlim, nx, show

x_values= [1,1,2,2,2,3,3,3,4,4,4,5,5,6,6,6]
bins = nx.arange(0.5, 7.)
hist(x_values, bins)
xlim(0,6.5)
show()

The grid line locations are determined by the xtick locations, which
you can set with the xticks command.

Good luck!
JDH
 
E

Enigma Curry

Thank you John. Your explanation helped a lot!

In case it helps anyone else in the future, here is my code for
*exactly* what I was after:

import pylab

def ryan_hist(data, bar_width, min_x, max_x):
"""
Create a frequency histogram over a continuous interval

min_x = the low end of the interval
max_x = the high end of the interval

bar_width = the width of the bars

This will correctly align the bars of the histogram
to the grid lines of the plot
"""
#Make histogram with bars of width .9 and center
#them on the integer values of the x-axis
bins = pylab.nx.arange(1-(bar_width/2),max(data))
n,bins,patches = pylab.hist(data, bins, width=bar_width)

#Make Y axis integers up to highest n
pylab.yticks(pylab.arange(sorted(n)[-1]))
pylab.axis('scaled')
pylab.xlim(0.5,6.5)
pylab.grid()
pylab.show()

#Create a historgram
data=[1,1,2,2,2,2,2,2,3,3,3,4,4,4,5,5,6,6,6]
bar_width = 0.9
ryan_hist(data,bar_width,min(data),max(data))
 
E

Enigma Curry

pylab.xlim(0.5,6.5)

should be:

pylab.xlim(min_x-(bar_width/2),max_x+(bar_width/2))
 
J

John Hunter

Enigma> pylab.xlim(0.5,6.5) should be:

Enigma> pylab.xlim(min_x-(bar_width/2),max_x+(bar_width/2))

Glad it's working better for you -- just a couple more smallish hints.

You might prefer to have your grid lines behind, rather than above the
bars. In that case create the subplot or axes with the axisbelow=True
kwarg. Despite the fact that you found the kwargs a little annoying
at first, you will probably come to love them. matplotlib makes very
heavy use of them and they are very useful since they allow matplotlib
to usually do the right things while exposing most of the settings to
you. Eg

plot(x, y,
linewidth=2, linestyle='--',
marker='o', markerfacecolor='r', markeredgecolor='g'
markeredgewith=2, markersize=10)

and so on. There are lots of properties you can set on almost every
command. Because noone wants to type all that, you can use aliases

plot(x, y, lw=2, ls='--', marker='o', mfc='r', mec='g', mew=2, ms=10)


Secondly, in your example, you are relying implicitly on matplotlib to
pick integer ticks for the xaxis. It's doing it right in this
example, but might prefer other tick locations for other examples
depending on your x_values. So set xticks explicitly.

Below is a slightly modified example showing these two ideas.

You also might want to consider joining the mailing list at

http://lists.sourceforge.net/mailman/listinfo/matplotlib-users

since you appear to be a little finicky about your figures :)

def ryan_hist(data, bar_width, min_x, max_x):
"""
Create a frequency histogram over a continuous interval

min_x = the low end of the interval
max_x = the high end of the interval

bar_width = the width of the bars

This will correctly align the bars of the histogram
to the grid lines of the plot
"""
#Make histogram with bars of width .9 and center
#them on the integer values of the x-axis
bins = pylab.nx.arange(1-(bar_width/2),max(data))
pylab.subplot(111, axisbelow=True)
n,bins,patches = pylab.hist(data, bins, width=bar_width)

#Make Y axis integers up to highest n
pylab.yticks(pylab.arange(max(n)))
pylab.xticks(pylab.arange(max(n)+1))
pylab.axis('scaled')
pylab.xlim(min_x-(bar_width/2),max_x+(bar_width/2))
pylab.grid()
pylab.show()
 
D

Dennis Lee Bieber

pylab.grid()
x_values=[1,1,2,2,2,3,3,3,4,4,4,5,5,6,6,6]
pylab.hist(x_values,6)
pylab.show()

This produced the following image:
http://enigmacurry.com/usenet/historgram-bars-not-in-grid-lines.png
Looks like it is trying to fit 6 bars into five divisions... IE, the
bar for value 1 starts to the right of the 1-vertical line. The
6-vertical line is the end of the graph, so the 6 bar has to be placed
to the left of it...

What happens if you specify a width of 7 (I'm presuming that is what
the second term in the pylab.hist() call controls).
--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top