A piece of Python code to compute a frequency table of a list of values
You may want to try 2.5.6, a security fix to 2.5.4.
Alternately either 2.7 or, preferably, 3 would be a better upgrade.
They may be unfeasible, but you should upgrade, you're 7 years behind!



First things first, don't do hacky stuff that give incorrect bounds.


  lowest = min(list) - 10**(-max(count)-1)


The correct bounds are not the ones you are using!
They are:

[0.1, 0.4)
[0.4, 0.7)
[0.7, 1.0]


All bar the last 1 inclusive is easy, just remove that hack you are using.
If we put the bound creator in a function then we can create the bounds and re-use them in a future function.
To handle the 1 inclusive you can change it to a 2, (1 + 1).

I would also use comprehensions, they are quite simple, but extremely useful.
For example creating count would be:

count = [num_after_point(list[i]) for i in range(len(list))]


This can be improved by not indexing list and not using len and range.

count = [num_after_point(i) for i in list]


As most of your function is creating the bounds I'll go through it first.
You want to keep most of your code the same. But:


Remove num_after_point, count and all that mess.
Remove all the bucketCountList stuff.
Change the while loop to a for loop for _ in range(numBuckets - 1):.
Yes you want the -1.
After changing low and high, yield them. (yield low, high).
After the for loop yield high, highest + 1, this is the only edge case we will be using.


This should get you:

def bounds(list_, numBuckets):
    lowest = min(list_)
    highest = max(list_)
    bucket_size = (highest - lowest) / numBuckets
    upper_bound = lowest
    for _ in range(numBuckets - 1):
        lower_bound, upper_bound = upper_bound, upper_bound + bucket_size
        yield lower_bound, upper_bound
    yield upper_bound, highest + 1


Now to use it is very easy:


You want to go through all the lower and upper bounds of the bounds function.
simply for l, u in bounds(...):.
Generate the sum in the bounds.
Display everything.


To get:

def histogram(list_, num_buckets):
    for lower_bound, upper_bound in bounds(list_, num_buckets):
        data = sum(lower_bound &lt;= i &lt; upper_bound for i in list_)
        print "From", lower_bound, "to", upper_bound, ":", data


The only down-side is the one hack we used to include the upper bound.
This has a small impact on the display, but ultimately it's a much nicer solution.


The bounds are easier to read.
You can use every number in the range. You couldn't use 0.0999999999 for example.


Finally, not knowing the numbers in the range is a bit... odd.
You should probably allow that, which is using a comprehensions if.

def histogram(list_, num_buckets):
    for lower_bound, upper_bound in bounds(list_, num_buckets):
        data = [i for i in list_ if lower_bound &lt;= i &lt; upper_bound]
        print "From", lower_bound, "to", upper_bound, ":", len(data)
        print data