1

How could I get a different pie chart color? I have a data set about 20 categories and it could be even larger. When I create a pie chart, some wedge have same color, so I wonder is there a way that I can have all colors different in my pie charts' wedge? Thanks!

Rui
  • 49
  • 1
  • 10
  • 1
    Does [this](https://stackoverflow.com/q/4805048/8881141) or [this](https://stackoverflow.com/q/16006572/8881141) answer your question? The cmap option is probably the best way for an unknown n although the colors might become quite similar with a high n number. – Mr. T Sep 02 '18 at 07:00
  • Does [this](https://matplotlib.org/1.5.0/examples/pie_and_polar_charts/pie_demo_features.html) answer your question? Please check out the `color=[colorlist]` option. – tif Sep 02 '18 at 12:14

1 Answers1

4

20 Colors is exactly the limits of what you can achieve through categorical/qualitative colormaps in matplotlib. Currently matplotlib provides the tab20, tab20b, tab20c colormaps.

import matplotlib.pyplot as plt
import numpy as np

data = np.random.randint(50,200, size=20)

fig = plt.figure()

with plt.style.context({"axes.prop_cycle" : plt.cycler("color", plt.cm.tab20.colors)}):
    ax = fig.add_subplot(121, aspect="equal")
    ax.pie(data)

with plt.style.context({"axes.prop_cycle" : plt.cycler("color", plt.cm.tab20c.colors)}):
    ax2 = fig.add_subplot(122, aspect="equal")
    ax2.pie(data)

plt.show()

enter image description here

For more colors one can of course also use different colormaps, but those will generally result in pretty similar colors next to each other. E.g. for a pie chart with 30 different colors we may use the nipy_spectral or the CMRmap colormap.

import matplotlib.pyplot as plt
import numpy as np

data = np.random.randint(50,200, size=30)

fig = plt.figure()

cc = plt.cycler("color", plt.cm.nipy_spectral(np.linspace(0,.9,len(data))))
with plt.style.context({"axes.prop_cycle" : cc}):
    ax = fig.add_subplot(121, aspect="equal")
    ax.pie(data)

cc = plt.cycler("color", plt.cm.CMRmap(np.linspace(0,0.9,len(data))))
with plt.style.context({"axes.prop_cycle" : cc}):
    ax2 = fig.add_subplot(122, aspect="equal")
    ax2.pie(data)

plt.show()

enter image description here

So one may add another dimension. Choosing some colors from any colormap and creating different luminosity levels for each of them. This is essentially shown in this answer. Here, in order to get e.g. 30 different colors we may choose 6 colors and for each 5 luminosity levels.

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.colors

def categorical_cmap(nc, nsc, cmap="tab10", continuous=False):
    if nc > plt.get_cmap(cmap).N:
        raise ValueError("Too many categories for colormap.")
    if continuous:
        ccolors = plt.get_cmap(cmap)(np.linspace(0,1,nc))
    else:
        ccolors = plt.get_cmap(cmap)(np.arange(nc, dtype=int))
    cols = np.zeros((nc*nsc, 3))
    for i, c in enumerate(ccolors):
        chsv = matplotlib.colors.rgb_to_hsv(c[:3])
        arhsv = np.tile(chsv,nsc).reshape(nsc,3)
        arhsv[:,1] = np.linspace(chsv[1],0.25,nsc)
        arhsv[:,2] = np.linspace(chsv[2],1,nsc)
        rgb = matplotlib.colors.hsv_to_rgb(arhsv)
        cols[i*nsc:(i+1)*nsc,:] = rgb       
    cmap = matplotlib.colors.ListedColormap(cols)
    return cmap

data = np.random.randint(50,200, size=30)

fig = plt.figure()

cc = plt.cycler("color", categorical_cmap(6, 5, cmap="tab10").colors)
with plt.style.context({"axes.prop_cycle" : cc}):
    ax = fig.add_subplot(121, aspect="equal")
    ax.pie(data)

cc = plt.cycler("color", 
                categorical_cmap(6, 5, cmap="gist_rainbow", continuous=True).colors)
with plt.style.context({"axes.prop_cycle" : cc}):
    ax2 = fig.add_subplot(122, aspect="equal")
    ax2.pie(data)

plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712