Data handling for matplotlib histogram with error bars
Question: I've got a data set which is a list of tuples in python like this:

    
    
    dataSet = [(6.1248199999999997, 27), (6.4400500000000003, 4), (5.9150600000000004, 1), (5.5388400000000004, 38), (5.82559, 1), (7.6892199999999997, 2), (6.9047799999999997, 1), (6.3516300000000001, 76), (6.5168699999999999, 1), (7.4382099999999998, 1), (5.4493299999999998, 1), (5.6254099999999996, 1), (6.3227700000000002, 1), (5.3321899999999998, 11), (6.7402300000000004, 4), (7.6701499999999996, 1), (5.4589400000000001, 3), (6.3089700000000004, 1), (6.5926099999999996, 2), (6.0003000000000002, 5), (5.9845800000000002, 1), (6.4967499999999996, 2), (6.51227, 6), (7.0302600000000002, 1), (5.7271200000000002, 49), (7.5311300000000001, 7), (5.9495800000000001, 2), (5.1487299999999996, 18), (5.7637099999999997, 6), (5.5144500000000001, 44), (6.7988499999999998, 1), (5.2578399999999998, 1)]
    

Where the first element of the tuple is an energy and the second a counter,
how many sensor where affected.

I want to create a histogram to study the relation between the number of
affected sensors and the energy. I'm pretty new to matplotlib (and python),
but this is what I've done so far:

    
    
    import math
    import matplotlib.pyplot as plt
    
    dataSet = [(6.1248199999999997, 27), (6.4400500000000003, 4), (5.9150600000000004, 1), (5.5388400000000004, 38), (5.82559, 1), (7.6892199999999997, 2), (6.9047799999999997, 1), (6.3516300000000001, 76), (6.5168699999999999, 1), (7.4382099999999998, 1), (5.4493299999999998, 1), (5.6254099999999996, 1), (6.3227700000000002, 1), (5.3321899999999998, 11), (6.7402300000000004, 4), (7.6701499999999996, 1), (5.4589400000000001, 3), (6.3089700000000004, 1), (6.5926099999999996, 2), (6.0003000000000002, 5), (5.9845800000000002, 1), (6.4967499999999996, 2), (6.51227, 6), (7.0302600000000002, 1), (5.7271200000000002, 49), (7.5311300000000001, 7), (5.9495800000000001, 2), (5.1487299999999996, 18), (5.7637099999999997, 6), (5.5144500000000001, 44), (6.7988499999999998, 1), (5.2578399999999998, 1)]
    
    binWidth = .2
    binnedDataSet = []
    #create another list and append the "binning-value"
    for item in dataSet:
        binnedDataSet.append((item[0], item[1], math.floor(item[0]/binWidth)*binWidth))
    
    energies, sensorHits, binnedEnergy = [[q[i] for q in binnedDataSet] for i in (0,1,2)]
    plt.plot(binnedEnergy, sensorHits, 'ro')
    plt.show()
    

This works so far (although it doesn't even look like a histogram ;-) but OK),
but now I want to calculate the mean value for each bin and append some error
bars.

What's the way to do it? I looked at histogram examples for matplotlib, but
they all use one-dimensional data which will be counted, so you get a
frequency spectrum… That's not really what I want.


Answer: I am somewhat confused by exactly what you are trying to do, but I think this
(to first order) will do what I think you want:

    
    
    bin_width = .2
    bottom = 5.0
    top = 8.0
    
    binned_data = [0.0] * int(math.ceil(((top - bottom) / bin_width)))
    binned_count = [0] * int(math.ceil(((top - bottom) / bin_width)))
    n_bins = len(binned_data)
    for E, cnt in dataSet:
        if E < bottom or E > top:
            print 'out of range'
            continue
        bin_id = int(math.floor(n_bins * (E - bottom) / (top - bottom)))
        binned_data[bin_id] += cnt
        binned_count[bin_id] += 1
    
    binned_avergaed_data = [C_sum / hits if hits > 0 else 0 for C_sum, hits in zip(binned_data, binned_count)]
    
    bin_edges = [bottom + j * bin_width for j in range(len(binned_data))]
    
    plt.bar(bin_edges, binned_avergaed_data, width=bin_width)
    

I would also suggest looking into `numpy`, it would make this much simpler to
write.

