66

I have a matplotlib plot generated with the following code:

import matplotlib.pyplot as pyplot

Fig, ax = pyplot.subplots()
for i, (mark, color) in enumerate(zip(
    ['s', 'o', 'D', 'v'], ['r', 'g', 'b', 'purple'])):
    ax.plot(i+1, i+1, color=color,
            marker=mark,
            markerfacecolor='None',
            markeredgecolor=color,
            label=i)

ax.set_xlim(0,5)
ax.set_ylim(0,5)
ax.legend()

with this as the generated figure: matplotlib generated figure

I don't like the lines through the markers in the legend. How can I get rid of them?

jlconlin
  • 14,206
  • 22
  • 72
  • 105

4 Answers4

104

You can specify linestyle="None" as a keyword argument in the plot command:

import matplotlib.pyplot as pyplot

Fig, ax = pyplot.subplots()
for i, (mark, color) in enumerate(zip(
    ['s', 'o', 'D', 'v'], ['r', 'g', 'b', 'purple'])):
    ax.plot(i+1, i+1, color=color,
            marker=mark,
            markerfacecolor='None',
            markeredgecolor=color,
            linestyle = 'None',
            label=`i`)

ax.set_xlim(0,5)
ax.set_ylim(0,5)
ax.legend(numpoints=1)
pyplot.show()

enter image description here

Since you're only plotting single points, you can't see the line attribute except for in the legend.

tom10
  • 67,082
  • 10
  • 127
  • 137
  • Interestingly this still "draws" (or allots space for) the line in the legend, look at the spacing in the legend between our answers. – Hooked Jan 22 '14 at 15:20
  • 2
    Personally, I think the symbols look good with a bit of space around them, though I would put in a bit less than is shown above if I were to optize it. The padding can also be tweeked with keyword arguments such as: `handletextpad=-.5, columnspacing=0, borderpad=-.5, borderaxespad=0`, etc, including `handlelength` which can be used as a keyword argument. – tom10 Jan 22 '14 at 17:14
  • 7
    uff, not `None` but `"None"` – bonobo Mar 12 '21 at 09:18
  • or simply `ls=' '` – Stardust Jun 09 '23 at 15:45
9

You can set the rcparams for the plots:

import matplotlib
matplotlib.rcParams['legend.handlelength'] = 0
matplotlib.rcParams['legend.numpoints'] = 1

enter image description here

All the legend.* parameters are available as keywords if you don't want the setting to apply globally for all plots. See matplotlib.pyplot.legend documentation and this related question:

legend setting (numpoints and scatterpoints) in matplotlib does not work

Community
  • 1
  • 1
Hooked
  • 84,485
  • 43
  • 192
  • 261
  • 1
    This is a good example for setting global parameters. I prefer @tom10' s answer for non-global settings. – jlconlin Jan 22 '14 at 15:28
8

To simply remove the lines once the data has been plotted:

handles, labels = ax.get_legend_handles_labels()
for h in handles: h.set_linestyle("")
ax.legend(handles, labels)
blalterman
  • 565
  • 7
  • 17
5

You should use a scatterplot here

import matplotlib.pyplot as pyplot

Fig, ax = pyplot.subplots()
for i, (mark, color) in enumerate(zip(
    ['s', 'o', 'D', 'v'], ['r', 'g', 'b', 'purple'])):
    ax.scatter(i+1, i+1, color=color,
            marker=mark,
            facecolors='none',
            label=i)

ax.set_xlim(0,5)
ax.set_ylim(0,5)
ax.legend(scatterpoints=1)

pyplot.show()
M4rtini
  • 13,186
  • 4
  • 35
  • 42
  • 1
    This was my first response, but I thought the example might have been too specific - what if the OP wants to have a true plot with multiple points? – Hooked Jan 22 '14 at 15:18
  • Ahh yes that might be the case. I just assumed he didn't know about the scatter plot function. If he really wanted a true plot with multiple points, he should go for one of the other answers here. – M4rtini Jan 22 '14 at 15:22
  • 1
    I did know about `scatter` plot. But I need something more generic. I just used `plot` here for an example. My current real application actually uses `errorbar`; `scatter` doesn't allow me to draw errorbars. – jlconlin Jan 22 '14 at 15:25