Make pie chart with percent readable in grayscale

I have source code for creating a pie chart

import matplotlib.pyplot as plt
from matplotlib.pyplot import savefig
import numpy as np
import matplotlib.gridspec as gridspec

plt.clf()
plt.cla()
plt.close()
labels_b = ["Negative",  "Positive"]
dev_sentences_b = [428, 444]
test_sentences_b = [912, 909]
train_sentences_b = [3310, 3610]

gs = gridspec.GridSpec(2, 2)
ax1= plt.subplot(gs[0, 0])
ax1.pie(train_sentences_b,  autopct='%1.1f%%',
        shadow=True, startangle=90)
ax1.axis('equal')
ax1.set_title("Train")

ax2= plt.subplot(gs[0, 1])
ax2.pie(dev_sentences_b, autopct='%1.1f%%',
        shadow=True, startangle=90)
ax2.axis('equal')
ax2.set_title("Dev")

ax3 = plt.subplot(gs[1, 1])
ax3.pie(test_sentences_b, autopct='%1.1f%%',
        shadow=True, startangle=90)
ax3.axis('equal')
ax3.set_title("Test")

ax3.legend(labels=labels_b, bbox_to_anchor=(-1,1), loc="upper left")

plt.savefig('sstbinary', format='pdf')

      

Result
Color photograph and grayscale
color-pie-chart

shades of gray

The grayscale version is a little difficult to read. Is there a suggestion to make a black and white pie chart readable in black and white print?

+3


source to share


2 answers


It's unclear if you want to create your chart in black and white already, or produce it in color and then convert it. The strategy in both cases can be the same: you can create a new color cycle using colors from the color map. A link to possible color codes is given here . Of course, you can also use your own color list.

eg. creating 5 colors from the color map gray

between 0.2

(dark gray) to 0.8

(lightgray):

from cycler import cycler
colors = plt.cm.gray(np.linspace(0.2,0.8,5))
plt.rcParams['axes.prop_cycle'] = cycler(color=colors)

      

enter image description here

Likewise, you can use a colorful map (for example magma

), which will still look good when converted to grayscale afterwards.

from cycler import cycler
colors = plt.cm.magma(np.linspace(0.2,0.8,5))
plt.rcParams['axes.prop_cycle'] = cycler(color=colors)

      

enter image description here

Changing the range of colors, eg. between 0.4

and 0.95

gives a lighter color,



from cycler import cycler
colors = plt.cm.magma(np.linspace(0.4,0.95,5))
plt.rcParams['axes.prop_cycle'] = cycler(color=colors)

      

enter image description here

Note that you can also apply colors directly to each pie chart instead of defining a color cycle.

ax.pie(..., colors=colors, ...)

      

Finally, a frequently used technique is to use shading to distinguish shapes in gray scale images. See this example .

pie = ax.pie(..., autopct='%1.1f%%', pctdistance=1.3,
              colors=colors, ...)
for patch, hatch in zip(pie[0],hatches):
    patch.set_hatch(hatch)

      

enter image description here

+3


source


Assuming you are storing the color digit and then converting to grayscale, you can do the following:

  • Identify the colors on the list from your favorite color card. [It's also worth noting here that using one of the new 4 color maps (available with matplotlib 1.5: viridis, magma, plasma, inferno) means the colors will still be distinguishable when the image is converted to grayscale].

    colors = plt.cm.plasma(np.linspace(0., 1., 5))
    
          

  • We can then define a function to convert these colors to their equivalent grayscale value:

    rgb2gray = lambda rgb: np.dot(rgb[...,:3], [0.299, 0.587, 0.114])
    
          

  • If this value is greater than 0.5, the color is a lighter shade and therefore we can use black text, otherwise change the text to a lighter color. We can store these text colors in a list using the following list comprehension:

    textcol = ['k' if rgb2gray(color) > 0.5 else 'w' for color in colors ]
    
          

  • When plotting your pie chart, use colors=colors

    kwarg to use the colors you defined earlier. matplotlib

    returns three things from ax.pie

    : patches that make up a pie chart, text labels, and labels autopct

    . The latter are the ones that we want to change.

    p, t, at = ax1.pie(train_sentences_b,  autopct='%1.1f%%',
            shadow=True, startangle=90, colors=colors)
    
          

  • Allows you to define a function for scrolling text labels and set their colors depending on the previously made list:

    def fix_colors(textlabels, textcolors):
        for text, color in zip(textlabels, textcolors):
            text.set_color(color)
    
          

  • We then call this after each pie chart has been plotted using:

    fix_colors(at, textcol)
    
          

Putting it all together in a script (I added some extra data to get all 5 categories in a pie chart):

import matplotlib.pyplot as plt
from matplotlib.pyplot import savefig
import numpy as np
import matplotlib.gridspec as gridspec

colors = plt.cm.plasma(np.linspace(0., 1., 5))

rgb2gray = lambda rgb: np.dot(rgb[...,:3], [0.299, 0.587, 0.114])

textcol = ['k' if rgb2gray(color) > 0.5 else 'w' for color in colors ]

def fix_colors(textlabels, textcolors):
    for text, color in zip(textlabels, textcolors):
        text.set_color(color)

plt.clf()
plt.cla()
plt.close()

labels_b = ["Very Negative", "Negative",  "Neutral", "Positive", "Very Positive"]
dev_sentences_b = [428, 444, 430, 500, 320]
test_sentences_b = [912, 909, 890, 900, 900]
train_sentences_b = [3310, 3610, 3200, 3500, 3321]

gs = gridspec.GridSpec(2, 2)
ax1= plt.subplot(gs[0, 0])
p, t, at = ax1.pie(train_sentences_b,  autopct='%1.1f%%',
        shadow=True, startangle=90, colors=colors)
fix_colors(at, textcol)

ax1.axis('equal')
ax1.set_title("Train")

ax2= plt.subplot(gs[0, 1])
p, t, at = ax2.pie(dev_sentences_b, autopct='%1.1f%%',
        shadow=True, startangle=90, colors=colors)
ax2.axis('equal')
ax2.set_title("Dev")
fix_colors(at, textcol)

ax3 = plt.subplot(gs[1, 1])
p, t, at = ax3.pie(test_sentences_b, autopct='%1.1f%%',
        shadow=True, startangle=90, colors=colors)
ax3.axis('equal')
ax3.set_title("Test")
fix_colors(at, textcol)

ax3.legend(labels=labels_b, bbox_to_anchor=(-1,1), loc="upper left")

plt.savefig('sstbinary', format='pdf')

      



Which gives the following image:

enter image description here

And after converting to grayscale:

enter image description here

+3


source







All Articles