Matt Pitkin Matt Pitkin - 1 month ago 20
Python Question

Is it possible to have two different marker styles for a label in a Matplotlib legend?

I want to customise a Matplotlib legend so that one of the labels is represented by two markers with different styles (e.g. ☆/▽ My label). I have seen that you can customise legend markers by making a patch for the marker, but can you create and use two patches (and at a push maybe add a "/" as a separator)? An option may also be to create a LaTeX string for the marker using TikZ, but that seems like overkill.

Answer

One way to do it would be to define custom markers using mathtext (see matplotlib documentation) and define the legend handle of the subclass with a proxy:

import numpy as np
import matplotlib.pyplot as plt

plt.close('all')

# Generate some data :

x1 = np.arange(1, 20)
y1 = np.log(x1) + np.random.uniform(-1, 1, size=len(x1))/5

x2 = np.arange(1, 20)
y2 = np.log(x2) + np.random.uniform(-1, 1, size=len(x2))/5

# Plot data :

fig, ax = plt.subplots()

h1, = ax.plot(x1[x1>5], y1[x1>5], ls='none', marker=r'$\star$',
              ms=12, mec='0.15', mfc='0.15', mew=1, alpha=0.5)

h2, = ax.plot(x2[x2>5], y2[x2>5], ls='none', marker=r'$\blacktriangledown$',
              ms=12, mec='0.15', mfc='0.15', mew=1, alpha=0.5)

ax.plot(x1[x1<=5], y1[x1<=5], ls='none', marker=r'$\star$',
        ms=12, mec='red', mfc='red', mew=1, alpha=0.5)

ax.plot(x2[x2<=5], y2[x2<=5], ls='none', marker=r'$\blacktriangledown$',
        ms=12, mec='red', mfc='red', mew=1, alpha=0.5)

# Create a proxy for the subclass :

h3, = ax.plot([], ls='none', marker=r'$\star/\blacktriangledown$',
              ms=24, mec='red', mfc='red', mew=1, alpha=0.5)


# Generate legend :

handles = [h1, h2, h3]
labels = ['dataset1', 'dataset2', 'transient state']
ax.legend(handles, labels, loc=4, ncol=1, numpoints=1, frameon=False)

# Save and show the figure :

fig.savefig('custom_legend_markers.png')
plt.show()

enter image description here