0

I am making a function which will make a list which includes a histogram of a requested list and requested values to use as the values of the histogram. Values above the requested value are included last.

The program is working with a list that is sorted in ascending order numerically, but when a list that is not sorted is used as input, the program seems to discard random values and not evaluate in the same way. the code:

def histogram(sample, binBoundaries):
    c=0
    if not binBoundaries:
        li = [len(sample)]
        return print(li)
    for x in sample:
        if x > binBoundaries[-1]: #if the value is greater than last bin
            c = c+1            #number of values greater increases
    for eachbin in binBoundaries: #for each bin
        dic[eachbin] = 0          #initial value = 0 to account for no number
        for x in sample:          #for each value wanted to calculate for
            if x <= eachbin:       #if the number falls into the bin
                dic[eachbin] += 1 #the number of values in the bin increases
            sample.remove(x)
    for i in dic:
        listofvalues.append(dic[i])
    listofvalues.append(c)
    print(listofvalues)

histogram([5, 4, 2, 3], [3])

this will result in an output of [1, 2], where the real output should be [2,2]

Is there something I'm just not seeing that is making the number not be calculated? Let me know where I have gone wrong if you could!

Benjamin
  • 3
  • 2

1 Answers1

1

Your problem is that you are removing items from the list sample while you are iterating over it, this is a bad idea because it will result in skipping some elements.

Try taking out the line sample.remove(x), you should get the expected result. If you really do need to remove elements from the input list you should refactor to make sure you still check every element in the list. One option is to iterate over the list in reverse using for x in reversed(sample).

It also looks like you may be removing elements in the wrong place, sample.remove(x) looks like it should be inside of the if directly above it. Try the following code:

    ...
    for eachbin in binBoundaries: #for each bin
        dic[eachbin] = 0          #initial value = 0 to account for no number
        for x in reversed(sample):          #for each value wanted to calculate for
            if x <= eachbin:       #if the number falls into the bin
                dic[eachbin] += 1 #the number of values in the bin increases
                sample.remove(x)
    ...
Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • That placement issue was the cause of all my problems, thank you so much! Now, a problem that arose with the program after that change was the inability to properly handle multiple numbers. But, with the reversing of the sample list, it fixed that as well. Why does the reversing help? – Benjamin Nov 16 '11 at 21:54
  • @Benjamin - [This answer](http://stackoverflow.com/questions/4301634/python-wont-remove-items-from-list/4301662#4301662) has a pretty good explanation of why removing while iterating causes problems. Reversing the list helps because you would be removing elements towards the end first, which would not affect the index of any elements earlier in the list. – Andrew Clark Nov 16 '11 at 22:12
  • I guess I could have also gotten around this issue by sorting the list with sorted() – Benjamin Nov 16 '11 at 22:16
  • Thanks for your insight F.J. That article helped me solve the rest of my assignment! – Benjamin Nov 17 '11 at 06:51