Search code examples
pythonhistogramstacked-chart

how to plot two histograms with stacked bars, without stacking all the bars together?


I have 4 histograms, lets say A,B,C and D. I would like to plot histograms A and B together, with stacked bars, along with histograms C and D, also with stacked bars, but without stacking the four histograms together. So I would like two stacked histograms in a single histogram with side-by-side bars.

So far, I can plot either A-B-C-D with stacked bars; or A-B and C-D in different stacked histograms, but the bars of both histograms are not side by side. is the code I have:

plot=[A,B,C,D] #values from 0-10
ww=[wA,wB,wC,wD] #weights

All bars stacked:

plt.hist(plot,bins=10,weights=ww,label=['A','B','C','D'],histtype="barstacked")

A-B histogram + C-D histogram, but one histogram hides the other:

plt.hist(plot[0:2],bins=10,weights=ww[0:2],label=['loses','wins'],stacked=True)
plt.hist(plot[2:4],bins=10,weights=ww[2:4],label=['l','w'],stacked=True)

thanks in advance for your help!


Solution

  • you can use the patches list that hist() returns:

    import numpy as np
    import matplotlib.pyplot as plt
    A = np.arange(100)
    B = np.arange(100)
    C = np.arange(100)
    D = np.arange(100)
    
    wA = np.abs(np.random.normal(size=100))
    wB = np.abs(np.random.normal(size=100))
    wC = np.abs(np.random.normal(size=100))
    wD = np.abs(np.random.normal(size=100))
    
    plot=[A,B,C,D] #values from 0-10
    ww=[wA,wB,wC,wD] #weights
    
    n, bins, patches = plt.hist(plot[0:2],bins=10,weights=ww[0:2],label=['loses','wins'],stacked=True)
    n, bins, patches2 = plt.hist(plot[2:4],bins=10,weights=ww[2:4],label=['l','w'],stacked=True)
    
    for patch in patches:
        plt.setp(patch, 'width', 10)
    for patch in patches2:
        plt.setp(patch, 'width', 5)    
    
    plt.show()
    

    histogram

    update

    I found out there's a much better and cleaner way to do this:

    import numpy as np
    import matplotlib.pyplot as plt
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    
    # the data
    A = np.arange(10)
    B = np.arange(10)
    C = np.arange(10)
    D = np.arange(10)
    
    wA = np.abs(np.random.normal(size=10))
    wB = np.abs(np.random.normal(size=10))
    wC = np.abs(np.random.normal(size=10))
    wD = np.abs(np.random.normal(size=10))
    ## necessary variables
    width = 0.5                      # the width of the bars
    ## the bars
    rects1 = ax.bar(A - width/2, wA, width,
                    color='blue')
    rects2 = ax.bar(B- width/2, wB, width, bottom=wA,
                    color='green')
    rects3 = ax.bar(C + width/2, wC, width,
                    color='red')
    rects4 = ax.bar(D + width/2, wD, width, bottom=wC,
                    color='yellow')
    # axes and labels
    ax.set_xlim(-width,len(A)+width)
    
    plt.show()
    

    the results it: better histogram

    for more details look at this link.