Partial coloring of text in matplotlib

PythonMatplotlib

Python Problem Overview


Is there a way in matplotlib to partially specify the color of a string?

Example:

plt.ylabel("Today is cloudy.")

How can I show "today" as red, "is" as green and "cloudy." as blue?

Thanks.

Python Solutions


Solution 1 - Python

I only know how to do this non-interactively, and even then only with the 'PS' backend.

To do this, I would use Latex to format the text. Then I would include the 'color' package, and set your colors as you wish.

Here is an example of doing this:

import matplotlib
matplotlib.use('ps')
from matplotlib import rc

rc('text',usetex=True)
rc('text.latex', preamble='\usepackage{color}')
import matplotlib.pyplot as plt

plt.figure()
plt.ylabel(r'\textcolor{red}{Today} '+
           r'\textcolor{green}{is} '+
           r'\textcolor{blue}{cloudy.}')
plt.savefig('test.ps')

This results in (converted from ps to png using ImageMagick, so I could post it here): enter image description here

Solution 2 - Python

Here's the interactive version. Edit: Fixed bug producing extra spaces in Matplotlib 3.

import matplotlib.pyplot as plt
from matplotlib import transforms

def rainbow_text(x,y,ls,lc,**kw):
    """
    Take a list of strings ``ls`` and colors ``lc`` and place them next to each
    other, with text ls[i] being shown in color lc[i].

    This example shows how to do both vertical and horizontal text, and will
    pass all keyword arguments to plt.text, so you can set the font size,
    family, etc.
    """
    t = plt.gca().transData
    fig = plt.gcf()
    plt.show()

    #horizontal version
    for s,c in zip(ls,lc):
        text = plt.text(x,y,s+" ",color=c, transform=t, **kw)
        text.draw(fig.canvas.get_renderer())
        ex = text.get_window_extent()
        t = transforms.offset_copy(text._transform, x=ex.width, units='dots')

    #vertical version
    for s,c in zip(ls,lc):
        text = plt.text(x,y,s+" ",color=c, transform=t,
                rotation=90,va='bottom',ha='center',**kw)
        text.draw(fig.canvas.get_renderer())
        ex = text.get_window_extent()
        t = transforms.offset_copy(text._transform, y=ex.height, units='dots')


plt.figure()
rainbow_text(0.05,0.05,"all unicorns poop rainbows ! ! !".split(), 
        ['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],
        size=20)

enter image description here

Solution 3 - Python

Extending Yann's answer, LaTeX coloring now also works with PDF export:

import matplotlib
from matplotlib.backends.backend_pgf import FigureCanvasPgf
matplotlib.backend_bases.register_backend('pdf', FigureCanvasPgf)

import matplotlib.pyplot as plt

pgf_with_latex = {
    "text.usetex": True,            # use LaTeX to write all text
    "pgf.rcfonts": False,           # Ignore Matplotlibrc
    "pgf.preamble": [
        r'\usepackage{color}'     # xcolor for colours
    ]
}
matplotlib.rcParams.update(pgf_with_latex)

plt.figure()
plt.ylabel(r'\textcolor{red}{Today} '+
           r'\textcolor{green}{is} '+
           r'\textcolor{blue}{cloudy.}')
plt.savefig("test.pdf")

Note that this python script sometimes fails with Undefined control sequence errors in the first attempt. Running it again is then successful.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGökhan SeverView Question on Stackoverflow
Solution 1 - PythonYannView Answer on Stackoverflow
Solution 2 - PythonPaul IvanovView Answer on Stackoverflow
Solution 3 - PythonFelixView Answer on Stackoverflow