Search code examples
pythonmatplotlibbar-chartoverlapping

Two bar charts in matplotlib overlapping the wrong way


I'm creating a bar plot with matplotlib in Python, and I'm having a bit of a problem with the overlapping bars:

import numpy as np
import matplotlib.pyplot as plt

a = range(1,10)
b = range(4,13)
ind = np.arange(len(a))
width = 0.65

fig = plt.figure()
ax = fig.add_subplot(111)

ax.bar(ind+width, a, width, color='#b0c4de')

ax2 = ax.twinx()
ax2.bar(ind+width+0.35, b, 0.45, color='#deb0b0')

ax.set_xticks(ind+width+(width/2))
ax.set_xticklabels(a)

plt.tight_layout()

Barplot

I want the blue bars to be in front, not the red ones. The only way I have managed to do so so far was to switch ax and ax2, but then the ylabels are going to be reversed as well, which I don't want. Isn't there a simple way to tell matplotlib to render ax2 before ax?

In addition, the ylabels on the right are being cut off by plt.tight_layout(). Is there a way to avoid this while still using tight_layout?


Solution

  • Perhaps there is a better way that I do not know about; however, you can swap ax and ax2 and also swap the location of the corresponding y-ticks with

    ax.yaxis.set_ticks_position("right")
    ax2.yaxis.set_ticks_position("left")
    

    import numpy as np
    import matplotlib.pyplot as plt
    
    a = range(1,10)
    b = range(4,13)
    ind = np.arange(len(a))
    width = 0.65
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.bar(ind+width+0.35, b, 0.45, color='#deb0b0')
    
    ax2 = ax.twinx()
    ax2.bar(ind+width, a, width, color='#b0c4de')
    
    ax.set_xticks(ind+width+(width/2))
    ax.set_xticklabels(a)
    
    ax.yaxis.set_ticks_position("right")
    ax2.yaxis.set_ticks_position("left")
    
    plt.tight_layout()
    plt.show()
    

    enter image description here


    By the way, instead of doing the math yourself, you can center the bars using the align='center' parameter:

    import numpy as np
    import matplotlib.pyplot as plt
    
    a = range(1,10)
    b = range(4,13)
    ind = np.arange(len(a))
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.bar(ind+0.25, b, 0.45, color='#deb0b0', align='center')
    
    ax2 = ax.twinx()
    ax2.bar(ind, a, 0.65, color='#b0c4de', align='center')
    
    plt.xticks(ind, a)
    ax.yaxis.set_ticks_position("right")
    ax2.yaxis.set_ticks_position("left")
    
    plt.tight_layout()
    plt.show()
    

    (The result is essentially the same as the above.)