Search code examples
pythonmatplotlibbar-chartdpiantialiasing

Bar plot with irregular spacing


I am using a bar chart to plot query frequencies, but I consistently see uneven spacing between the bars. These look like they should be related to to the ticks, but they're in different positions

This shows up in larger plots bar chart 0 to 2000 with irregular spacing

And smaller ones bar chart 0 to 100 with irregular spacing


def TestPlotByFrequency (df, f_field, freq, description):
    import matplotlib.pyplot as plt

    fig, ax = plt.subplots()
    ax.bar(df[f_field][0:freq].index,\
           df[f_field][0:freq].values)


    plt.show()

This is not related to data either, none at the top have the same frequency count

    count
0   8266
1   6603
2   5829
3   4559
4   4295
5   4244
6   3889
7   3827
8   3769
9   3673
10  3606
11  3479
12  3086
13  2995
14  2945
15  2880
16  2847
17  2825
18  2719
19  2631
20  2620
21  2612
22  2590
23  2583
24  2569
25  2503
26  2430
27  2287
28  2280
29  2234
30  2138

Is there any way to make these consistent?


Solution

  • The problem has to do with aliasing as the bars are too thin to really be separated. Depending on the subpixel value where a bar starts, the white space will be visible or not. The dpi of the plot can either be set for the displayed figure or when saving the image. However, if you have too many bars increasing the dpi will only help a little.

    As suggested in this post, you can also save the image as svg to get a vector format. Depending where you want to use it, it can be perfectly rendered.

    import matplotlib
    import matplotlib.pyplot as plt
    import pandas as pd
    import numpy as np
    
    matplotlib.rcParams['figure.dpi'] = 300
    
    t = np.linspace(0.0, 2.0, 50)
    s = 1 + np.sin(2 * np.pi * t)
    
    df = pd.DataFrame({'time': t, 'voltage': s})
    
    fig, ax = plt.subplots()
    ax.bar(df['time'], df['voltage'], width = t[1]*.95)
    
    plt.savefig("test.png", dpi=300)
    plt.show()
    

    Image with 100 dpi: 100 dpi image

    Image with 300 dpi: 300 dpi image