Search code examples
pythonmatplotlibhistogram

Many plots on one graph (horizontal and vertical) in matplotlib


Hey this is the plot which I want to create enter image description here

And here are the details: on x axis I want to have the numbers from 0 to 10, on y axis I want to have values from 0 do 60. For each i from interval [0, 10], I have 10000 numbers. Black line is the mean of all the numbers for each i. For selected is (i=2 and i=6 on the graph) I want to plot histogram vertically. What is important I want to use density=True in hist function. The most difficult part is to fix the height of all the histograms to 3 in terms of x axis values (red one starts at 2 and the highest point is at 5 and the blue one starts at 6 and ends at 9 so the height is 3). Is anyone able to help me? Below is my current code and the plot which is produced - unfortunately the height is much too small.

import numpy as np
import matplotlib.pyplot as plt

x = range(11)
res = np.random.randint(0, 60, size = (11, 10000))

means = [res[i, :].mean() for i in x]

fig, ax = plt.subplots(figsize = (12, 6), dpi = 300)

ax.plot(x, means)
ax.hist(res[2,:], bins = 100, density = True, orientation = 'horizontal', bottom = 2)

enter image description here


Solution

  • Here is a stab at it - ax.hist returns n,bins, and patches. We can modify the patches object (aka the rectangles) to set a height (i.e. width in this case because the orientation is horizontal) following the methods suggested in Setting the Height of Matplotlib Histogram.

    import matplotlib.pyplot as plt
    import numpy as np
    
    if __name__ == "__main__":
    
        x = range(11)
        res = np.random.randint(0, 60, size=(11, 10000))
    
        means = [res[i, :].mean() for i in x]
    
        # Start of figure
        fig, ax = plt.subplots(figsize=(12, 6))
    
        # Red histogram
        n_red, bins_red, rects_red = ax.hist(res[2,:], bins=100, density=True, bottom=2, orientation="horizontal",
                                             rwidth=0.7, color='r', label='Hist i=2')
    
        scalar_height = 3
        # The values are less than 1, we can just take the value and add 3 to artificially increase the height to 3
        for r_red in rects_red:
            r_red.set_width(r_red.get_width() + scalar_height)
    
        # Blue histogram
        n_blue, bins_blue, rects_blue = ax.hist(res[6,:], bins=100, density=True, bottom=6, orientation="horizontal",
                                                rwidth=0.7, color='b', label='Hist i=6')
    
        for r_blue in rects_blue:
            r_blue.set_width(r_blue.get_width() + scalar_height)
    
        ax.plot(x, means, 'k', label='Average per i')
    
        ax.set_xlim([0, 10])
        ax.set_ylim([0, 60])
        ax.set_xlabel("i")
        ax.legend()
    
        plt.tight_layout()
        plt.show()
    

    Example histogram with new width