Chicrala
Chicrala

Reputation: 1054

How to correctly position the bars on a bar plot

I'm trying to produce bar plots for histograms I'm calculating over a set of images using numpy however my plots are not actually plotting the bars on the axes. The code I'm using is:

def makebarplot(bins, values, title = None, export = False,
              path = None, file_name = None):
    '''
    This function will take the outputs
    of np.histogram results and make a 
    barplot of it.
    '''
    #creating the object
    img, ax1 = plt.subplots(figsize = (13,8))

    ax1.bar(bins[:-1],values)

    #adjusting the graphic
    ax1.set_xscale('log')
    ax1.set_yscale('log')
    ax1.set_xlabel('Values')
    ax1.set_xticks(bins)
    ax1.set_ylabel('Frequency')
    ax1.set_title(title)

    plt.show()

    if export is True:
        #saving figure
        img.savefig(path+file_name, bbox_inches = 'tight')

    #closing the plot    
    #plt.close()

    return

#the bins I'm using
bins = [1e1**i for i in range(2,20)]

#the values I'm entering they are the frequency of
# values in between each of the corresponding 
#bins defined above
values = [0.000000e+00, 0.000000e+00, 0.000000e+00, 0.000000e+00, 
          1.000000e+00, 1.000000e+01, 1.100000e+02, 8.870000e+02, 
          6.582000e+03, 4.542300e+04, 2.630240e+05, 1.090866e+06, 
          2.281769e+06, 1.199336e+06, 4.057230e+05,
          6.878300e+04, 1.211000e+03]

makebarplot(bins,ar_values)

The result I am having from this is: current attempt

This plot should look something like a bar version of this: enter image description here

What am I missing?

I was consulting a post that suggests this may be happening due to an incorrect position of the bars however, I failed to grasp the concept of how that may be connected to my data or if I'm missing something else.

Also I can't understand why I had to trim one of the bins so the values and bins should have the same length. Since the results would fit in between then naturally I would assume that the bins have one more length than the list containing the values.

Upvotes: 1

Views: 538

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339052

Only because you name the positions of the bars bins, does not mean they become bins. (As in "I named my car 'Ferrari', but it didn't become red.")

So what happens here is that the bars are placed at the left bin edges (as you specified bins[:-1] as positions). However the width of the bars is not specified, so matplotlib takes the default 1 unit bar width. One unit on a scale that spans over 20 orders of magnitude is really tiny; in fact on the 13 inches wide figure with a dpi of 100, your resolution is something like 7e14 units per pixel, which is much larger then 1.

At the end it would probably make sense to define the width of the bars as well. You would then also need to align the bars to their left edge.

ax1.bar(bins[:-1],values, width=np.diff(bins), align="edge", ec="k")

(Here np is numpy)

enter image description here

Note that the first 4 bars are missing because their height is 0, which is undefined on a log scale.

Upvotes: 1

Related Questions