Search code examples
pythonmatplotlibplotlimitgradient

Adjust bar plot gradient with x axis limit


I have a bar plot with gradient colours on the bar, however when I change the x-axis limits, the gradient is still applied to the original x values (i.e. changing the x-axis limits from 0-10 to 5-10, the gradient is still applied to 0-10 and the new plot only shows half of the gradient):

enter image description here enter image description here

I used this function which applies a gradient colour to bars in matplotlib:

def gradientbars(bars):
    '''Function to apply gradient colour over bars'''
    grad = np.atleast_2d(np.linspace(0,1,256))
    ax = bars[0].axes
    lim = ax.get_xlim()+ax.get_ylim()
    for bar in bars:
        bar.set_zorder(1)
        bar.set_facecolor("none")
        x,y = bar.get_xy()
        w, h = bar.get_width(), bar.get_height()
        ax.imshow(grad, extent=[x,x+w,y,y+h], aspect="auto", zorder=0, cmap = "Blues")
    ax.axis(lim)

And this function to plot the bar plot:

def bar_plot(position, x_axis, title):

    # Opening figure & axis
    fig, ax = plt.subplots()
    # Creating scatter plot
    bar = ax.barh(position['Player'], position[x_axis])
    # Applying gradient function
    gradientbars(bar)
    # Setting x-axis limits
    plt.xlim([5, 10])

Is it possible to alter the code so that the gradient is applied to the new plot with x-axis limits?


Solution

  • The ax.imshow() is where the color gradient is set. As you will start your plot at x=5, you will need to set the extent also to start at that position. More information on extent is available here. Note that is hard coded to 5, but you can send a variable with the number you want. A fully running example is given below to showcase the same.

    def gradientbars(bars):
        '''Function to apply gradient colour over bars'''
        grad = np.atleast_2d(np.linspace(0,1,256))
        ax = bars[0].axes
        lim = ax.get_xlim()+ax.get_ylim()
        for bar in bars:
            bar.set_zorder(1)
            bar.set_facecolor("none")
            x,y = bar.get_xy()
            w, h = bar.get_width(), bar.get_height()
            ##Changed the start of x from x to x+5 so the gradient starts there
            ax.imshow(grad, extent=[x+5,x+w,y,y+h], aspect="auto", zorder=0, cmap = "Blues")
        ax.axis(lim)
        
    def bar_plot(position, x_axis, title):
    
        # Opening figure & axis
        fig, ax = plt.subplots()
        # Creating scatter plot
        bar = ax.barh(position['Player'], position[x_axis])
        # Setting x-axis limits
        plt.xlim([5, 10])
        # Applying gradient function
        gradientbars(bar)
        
    df=pd.DataFrame({'x': np.random.randint(6, 10, size=(10)), 'Player' : np.arange(1,11)}) ## Random data BETWEEN 5-11
    bar_plot(df, 'x','Ploty plot')
    

    Plot

    enter image description here