Search code examples
pythonmatplotlibplotprettyplotlib

prettyplotlib labels and annotations are off-centred


Why are annotations of prettyplotlib barchat and x-axis labels off-centered?

Using prettyplotlib==0.1.7

If we create a normal barchart with the x-axis as defined by the 2nd argument, the labels are well centred on the bar:

%matplotlib inline
import numpy as np
import prettyplotlib as ppl
import matplotlib.pyplot as plt

fig, ax = plt.subplots(1)

counter = {1:1, 2:4, 3:9, 4:16, 5:25, 6:36, 7:49}

x, y = zip(*counter.items())

ppl.bar(ax, x , y, grid='y')

[out]:

enter image description here

But if we use the xticklabels the x-axis labels goes off-center:

ppl.bar(ax, x , y, xticklabels=list('1234567'), grid='y')

[out]:

enter image description here

Similarly, when we use the annotate=True argument, it goes off-center:

ppl.bar(ax, x , y, annotate=True, grid='y')

[out]:

enter image description here

It's unlike the examples shown on https://github.com/olgabot/prettyplotlib/wiki/Examples-with-code#hist


Solution

  • I would recommend not using prettyplotlib any more. It's 3 years old and all it's basically doing is to change the style of the plots. Better use matplotlib directly and if you are not happy with the style, use a different one or create your own. If you encounter problems, questions about changing the style also have a very high chance of being answered here.

    Here is a way how to change the style to recreate the plot from the above question.

    import matplotlib.pyplot as plt
    
    style = {"axes.grid" : True,
             "axes.grid.axis" : "y",
             "axes.spines.top"  : False,
             "axes.spines.right"  : False,
             "grid.color" : "white",
             "ytick.left" : False,
             "xtick.bottom" : False,
             }
    plt.rcParams.update(style)
    
    counter = {1:1, 2:4, 3:9, 4:16, 5:25, 6:36, 7:49}
    x, y = zip(*counter.items())
    
    fig, ax = plt.subplots(1)
    ax.bar(x , y, color="#66c2a5" )
    
    plt.show()
    

    enter image description here

    Now you are free to set different xticklabels,

    ax.set_xticks(x)
    ax.set_xticklabels(list("ABCDEFG"))
    

    Or annotate the the bars,

    for i,j in zip(x,y):
        ax.annotate(str(j), xy=(i,j), xytext=(0, 4),textcoords='offset points',ha="center")
    

    enter image description here

    The matplotlib documentation is pretty well maintained and there are lots of question here to help you do your special case plots if ever needed.