Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom marker edge style in manual legend

I want to create a legend for a plot manually which does not directly refer to any data in the plot, such as:

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

plt.plot([0, 1], [3, 2])
line = Line2D([], [], label='abc', color='red', linewidth=1.5, marker='o',
              markerfacecolor='yellow', markeredgewidth=1.5, markersize=16)
plt.legend(handles=[line], numpoints=1)
plt.show()

Resulting plot

This works great except because I cannot find a way of setting the marker edge style (i.e. solid, dashed, dotted, etc.) as well. There is no markeredgestyle property or similar for a Line2D, and setting the linestyle instead does not seem to affect the marker edge style. Is there any workaround for this?

A few approaches come to my mind but I am not sure of how feasible they are:

  • Use something entirely different from Line2D. It would need to be showable in the legend, have the same formatting options as Line2D, plus the extra marker edge style. Not sure if such a class exists
  • Create a custom class derived from Line2D and implement that marker edge style myself
  • Create the data in the plot itself, then remove it from there while keeping it in the legend somehow. Not sure if a class which allows me to do this even in the actual chart exists. Note that it has to contain both a marker and a line. Closest thing I can think of is using scatter for the markers and plot for the lines, but that would show two legend entries (unless there is a way to combine those into a single one)

Ideally, the line style and the marker edge style could be different, but if there is a way to change the marker edge style which involves overwriting the line style I would also take it.

I am using matplotlib 1.5.3.

like image 335
FernAndr Avatar asked Dec 24 '22 14:12

FernAndr


1 Answers

You may use a special marker symbol, which has a dotted edge, e.g. marker=ur'$\u25CC$' (Complete STIX symbol table).

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

plt.plot([0, 1], [3, 2])
line = Line2D([], [], label='abc', color='red', linewidth=1.5, marker=ur'$\u25CC$',
              markeredgecolor='indigo', markeredgewidth=0.5, markersize=16)
plt.legend(handles=[line], numpoints=1)
plt.show()

enter image description here

This however cannot be filled.

On the other hand, a scatter plot does not have any connecting lines, such that the linestyle of a scatter affects indeed the marker edge. You may hence combine a Line2D and a scatter, where the line has no marker and constitutes the background line and the scatter is responsible for the marker.

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

plt.plot([0, 1], [3, 2])
line = Line2D([], [], label='abc', color='red', ls="-", linewidth=1.5)
sc1 = plt.scatter([],[],s=14**2,facecolors='yellow', edgecolors='blue',
            linestyle='--')
sc2 = plt.scatter([],[],s=14**2,facecolors='gold', edgecolors='indigo',
            linestyle=':', linewidth=1.5)
plt.legend([(line,sc1), (line,sc2)], ["abc", "def"], numpoints=1)

plt.show()

enter image description here

like image 168
ImportanceOfBeingErnest Avatar answered Jan 16 '23 04:01

ImportanceOfBeingErnest