pythonmatplotlibhistogramxticks

Can't Align Histogram Bin Edges with Chart Even When Using Numpy histogram_bin_edges


I want the histogram edges to line up with the xticks of my chart. Other SO and answers I've read focus on calculating the bins and passing them. I've done this yet still can't get them to align: histogram whose chart and xticks do not align

I've focused on the following lines to get this to work with no luck. In my_bins I tried converting it to a list (tolist()), and even with forcibly changing the xticks to match my_bins it doesn't align.

my_bins = np.histogram_bin_edges(a=dataframe[data_cols].values.ravel(), bins='sqrt').tolist()

axes_dict['histogram'].set_xticks(ticks=my_bins)

axes_dict['histogram'].set_xticklabels(labels=my_bins)

What should I try next?

Here's my sample code:

    from matplotlib.figure import Figure
    from PIL import Image
    import pandas as pd 
    import numpy as np
    my_fig = Figure(**{'layout': 'constrained'})
    mosaic = {'mosaic': [['histogram']], 'gridspec_kw': {'wspace': 0.0, 'hspace': 0.0}}
    axes_dict = my_fig.subplot_mosaic(**mosaic)
    columns = ['label', 'obs1']
    data = [('', 74.03), ('', 73.995), ('', 73.988), ('', 74.002), ('', 73.992), ('', 74.009), ('', 73.995), ('', 73.985), ('', 74.008), ('', 73.998), ('', 73.994), ('', 74.004), ('', 73.983), ('', 74.006), ('', 74.012), ('', 74.0), ('', 73.994), ('', 74.006), ('', 73.984), ('', 74.0), ('', 73.988), ('', 74.004), ('', 74.01), ('', 74.015), ('', 73.982)]
    dataframe = pd.DataFrame(data, columns=columns)
    data_cols = ['obs1']
    my_bins = np.histogram_bin_edges(a=dataframe[data_cols].values.ravel(), bins='sqrt').tolist()
    # my_bins = [73.982, 73.9916, 74.0012, 74.0108, 74.0204, 74.03]
    axes_dict['histogram'].hist(**{'x': [74.03, 73.995, 73.988, 74.002, 73.992, 74.009, 73.995, 73.985, 74.008, 73.998, 73.994, 74.004, 73.983, 74.006, 74.012, 74.0, 73.994, 74.006, 73.984, 74.0, 73.988, 74.004, 74.01, 74.015, 73.982], 'bins': [73.982, 73.9916, 74.0012, 74.0108, 74.0204, 74.03], 'label': '', 'color': 'C0', 'zorder': 3.0, 'alpha': 0.5, 'histtype': 'step', 'align': 'left', 'orientation': 'vertical'})
    axes_dict['histogram'].set_xticks(ticks=my_bins)
    axes_dict['histogram'].set_xticklabels(labels=my_bins)
    my_fig.savefig('example_figure_for_stackoverflow.png')
    Image.open('example_figure_for_stackoverflow.png').show()

Solution

  • Here it is the figure!

    The figure above was produced by the code below

    import matplotlib.pyplot as plt
    
    x = [74.030, 73.995, 73.988, 74.002, 73.992,
         74.009, 73.995, 73.985, 74.008, 73.998,
         73.994, 74.004, 73.983, 74.006, 74.012,
         74.000, 73.994, 74.006, 73.984, 74.000,
         73.988, 74.004, 74.010, 74.015, 73.982]
    
    counts, bin_limits, bars = plt.hist(x, bins=5, histtype='step', 
                                        facecolor='none', edgecolor='grey')
    plt.xticks(bin_limits)
    plt.show()
    

    Otherwise, one can pre-define the bin limits as the OP apparently wants, passing a list with the desired bin boundaries to plt.hist.

    enter image description here

    The figure above was produced by the code below

    import matplotlib.pyplot as plt
    
    x = [74.030, 73.995, 73.988, 74.002, 73.992,
         74.009, 73.995, 73.985, 74.008, 73.998,
         73.994, 74.004, 73.983, 74.006, 74.012,
         74.000, 73.994, 74.006, 73.984, 74.000,
         73.988, 74.004, 74.010, 74.015, 73.982]
    bins = [73.98+i*0.01 for i in range(6)]
    (
    counts,
    bin_limits,
    bars
    ) = plt.hist(x, histtype='step', bins=bins,
                 facecolor='none', edgecolor='grey')
    plt.xticks(bin_limits)
    plt.show()