Search code examples
pythonmatplotlibgradientpie-chartcolormap

Matplotlib pie chart wedges using color gradient


I am trying to create a pie chart with each wedge having a different color gradient (e.g., yellow-green) instead of a single color (e.g., green). To further explain, the gradient should be set along the radius and not the circumference of the pie.

Tried many options and did some research online but couldn't find a direct solution to this.

Is there a library or approach I should take to achieve this?

Thanks in advance.


Solution

  • You can create an image with the desired gradient, and position and clip it via each wedge. LinearSegmentedColormap.from_list() interpolates between given colors.

    Here is an example:

    import matplotlib.pyplot as plt
    from matplotlib.colors import LinearSegmentedColormap
    import numpy as np
    
    fig, ax = plt.subplots()
    
    sizes = np.random.uniform(10, 20, 4)
    color_combos = [('yellow', 'green'), ('red', 'navy'), ('yellow', 'crimson'), ('lime', 'red')]
    wedges, texts = ax.pie(sizes, labels=['alpha', 'beta', 'gamma', 'delta'])
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    for wedge, color_combo in zip(wedges, color_combos):
        wedge.set_facecolor('none')
        wedge.set_edgecolor('black')
        print(wedge.theta1, wedge.theta2)
        bbox = wedge.get_path().get_extents()
        x0, x1, y0, y1 = bbox.xmin, bbox.xmax, bbox.ymin, bbox.ymax
        x = np.linspace(x0, x1, 256)[np.newaxis, :]
        y = np.linspace(y0, y1, 256)[:, np.newaxis]
        # fill = np.sqrt(x ** 2 + y ** 2) # for a gradient along the radius, needs vmin=0, vmax=1
        fill = np.degrees(np.pi - np.arctan2(y, -x))
        gradient = ax.imshow(fill, extent=[x0, x1, y0, y1], aspect='auto', origin='lower',
                             cmap=LinearSegmentedColormap.from_list('', color_combo),
                             vmin=wedge.theta1, vmax=wedge.theta2)
        gradient.set_clip_path(wedge)
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)
    ax.set_aspect('equal')
    plt.show()
    

    At the left an example of a gradient along the angle, at the right a gradient along the radius.

    pie chart with gradient fill