Search code examples
pythonmatplotlibrangehistogramstep

How do I make a mathplotlib histogram seperated with ranges by a specific step?


I would like to make an histogram that shows grades (for example), and I want to be able to give mathplotlib a specific step size to make the bin ranges from it.

For example, if the given step size is 16, I want the histogram to look like this: Example

I tried doing this like:

def custom_histogram(lst, high_bound, low_bound, step):
  bounds_dif = high_bound-low_bound
  if bounds_dif%step == 0:
    bin = int((high_bound-low_bound)/step)
  else:
    bin = int((high_bound-low_bound)/step) + 1

  plt.hist(lst, bin, ec="white")
  plt.show()

But then the ranges are divided equally, and not as steps (for example the last bin is not 96-100).


Solution

  • Solution

    In the matplotlib documentation, it says:

    If bins is a sequence, it defines the bin edges, including the left edge of the first bin and the right edge of the last bin; in this case, bins may be unequally spaced. All but the last (righthand-most) bin is half-open.

    Thus you can do:

    # The first and last bins will be inclusive
    bins = list(range(0, max(lst), step) + [max(lst)] 
    
    plt.hist(lst, bins, ec="white")   
    

    If you want to keep the possibility to keep your custom bounds:

    bins = list(range(low_bound, high_bound, step)) + [high_bound] 
    
    plt.hist(lst, bins, ec="white")       
    

    How to set the same width to the last bar ?

    The last bar might be thinner than the others. The trick is to apply the same width than another bar.

    # We need to get the Axe. This is one solution.
    fig, ax = plt.subplots()
    bins = list(range(low_bound, high_bound, step)) + [high_bound] 
    
    ax.hist(lst, bins, ec="white")   
    # Applies the width of the first Rectangle to the last one
    ax.patches[-1].set_width(ax.patches[0].get_width())
    

    Before :

    Hist plot before

    After :

    Hist plot after