[Tutor] Graphing the random.gauss distribution

Dick Moores rdm at rcblue.com
Tue Aug 14 18:29:48 CEST 2007


At 06:47 AM 8/14/2007, Kent Johnson wrote:
>Dick Moores wrote:
> > Kent Johnson posted this to Tutor list Aug 8, 2007
> > (<http://mail.python.org/pipermail/tutor/2007-August/056194.html>):
> >
> > ============================================
> >  > Python provides you with a pseudo random number generator whose output
> >  > values are uniformly distributed between the input parameters.  What you
> >  > are dealing with in fish weights or test scores or other natural
> >  > phenomena is most likely a normal distribution. Check out Wikipedia's
> >  > normal distribution entry.  The math is really juicy. You may end up
> >  > with a recipe for the Python Cookbook.
> >
> > No need for all that, use random.gauss()
> >
> > Kent
> > ============================================
> >
> > I hadn't noticed gauss was there in the Random module. I got to
> > wondering if I could graph the distribution. This code produces a
> > nice bell-curve-seeming curve (on its side). Takes about 80 secs to
> > run on my computer. To fit your situation, the length of the bars can
> > be shortened or lengthened by decreasing or increasing, respectively,
> > the divisor of gaussCalls in line 5, "barLengthAdjuster = 
> gaussCalls//2600".
> >
> > Dick Moores
> >
> > ==============================
> > from random import gauss
> > mean = 100
> > std = 10
> > gaussCalls = 10000000
> > barLengthAdjuster = gaussCalls//2600
> >
> > d = []
> > for k in range(200):
> >      d.append([k, 0])
>
>This could be a list comprehension:
>d = [ [k, 0] for k in range(200) ]

So you recommend using list comprehensions wherever possible? (I sure 
wouldn't have thought of that one..)

>but there is no need to keep the array index in the array so this is
>simpler:
>
>d = [0] * 200
>
> > for k in xrange(gaussCalls):
> >      n = int(gauss(mean, std))
> >      d[n][1] += 1
>
>This becomes just
>       d[n] += 1
>
> >
> > for c in d:
> >      barLength = c[1]//barLengthAdjuster
> >      print barLength, "=", c[0], c[1]

By the time my code got into my post, I had changed "print barLength 
* "=", c[0], c[1]"  to  "print barLength, "=", c[0], c[1]", thinking 
upon reading it over that the "*" was a mistake. :-(   The code I 
didn't send DID make bars out of "="s.

>Use enumerate() to get the indices as well as the list contents. This
>version prints an actual bar as well:
>for i, count in enumerate(d):
>       barLength = count//barLengthAdjuster
>       print i, '*' * barLength, count

Ah, enumerate() is nice! I'd forgotten about it. And "*" IS better 
for bars than "=".

I prefer the index (or integer) to come after the bar ends, and 
before the count. One reason is that if the index is at the base of 
the bar, at 100 and above, the bars get pushed out one character 
longer than they should be relative to the 99 or less bars. I suppose 
there's a way to handle this, but I couldn't think of it then (but see below).

So this is my code now:

====================================
from random import gauss
mean = 100
std = 10
gaussCalls =1000000
barLengthAdjuster = gaussCalls//2600

d = [0] * 200

for k in xrange(gaussCalls):
     n = int(gauss(mean, std))
     d[n] += 1

for i, count in enumerate(d):
     barLength = count//barLengthAdjuster
     print '*' * barLength, i, count
=====================================

This would solve the problem I mentioned above caused by putting the 
indices at the bases of the bars:

for i, count in enumerate(d):
     barLength = count//barLengthAdjuster
     if i < 100:
         print "%d  %s %d" % (i, '*' * barLength, count) # there are 
2 spaces between %d and %s
     else:
         print "%d %s %d" % (i, '*' * barLength, count)

Thanks very much, Kent, for taking the time to advise me on my code.

Dick 



More information about the Tutor mailing list