274

In Python, with Matplotlib, how can a scatter plot with empty circles be plotted? The goal is to draw empty circles around some of the colored disks already plotted by scatter(), so as to highlight them, ideally without having to redraw the colored circles.

I tried facecolors=None, to no avail.

1
  • 1
    People looking to draw empty/hollow scatter plots with different colors may look at this question. Commented Mar 25, 2018 at 18:03

7 Answers 7

410

From the documentation for scatter:

Optional kwargs control the Collection properties; in particular:

    edgecolors:
        The string ‘none’ to plot faces with no outlines
    facecolors:
        The string ‘none’ to plot unfilled outlines

Try the following:

import matplotlib.pyplot as plt 
import numpy as np 

x = np.random.randn(60) 
y = np.random.randn(60)

plt.scatter(x, y, s=80, facecolors='none', edgecolors='r')
plt.show()

example image

Note: For other types of plots see this post on the use of markeredgecolor and markerfacecolor.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks! The gotcha is that the more usual (in Python) facecolors=None does not work, which tripped me.
Very helpful. It's markerfacecolor='none', this is the way it's now.
I had my matplotlib style in a way that set the edges widths to zero. If you don't see any markers with markerfacecolor='none' try adding markeredgewidth=1.0
This approach can also be used in Seaborn after doing the standard import of Matplotlib %matplotlib inline and import matplotlib.pyplot as plt, and then setting Seaborn to be the plotting default by import seaborn as sns; sns.set()
The edge widths are currently (v3.4.2) specified by the parameter linewidths instead of markeredgewidth. Documentation
|
107

Would these work?

plt.scatter(np.random.randn(100), np.random.randn(100), facecolors='none')

example image

or using plot()

plt.plot(np.random.randn(100), np.random.randn(100), 'o', mfc='none')

example image

4 Comments

this is useful for when you use plot instead of scatter
For scatter, you need to specify edgecolors like edgecolors='r'. Otherwise, the circles disappear. See here
@T_T If I specify edgecolors='r' I have to specify a color by hand. Is there a way to have the empty circles not disappear, but letting PyPlot choose automatic the colors for each series?
@becko No idea, sorry.
15

Here's another way: this adds a circle to the current axes, plot or image or whatever :

from matplotlib.patches import Circle  # $matplotlib/patches.py

def circle( xy, radius, color="lightsteelblue", facecolor="none", alpha=1, ax=None ):
    """ add a circle to ax= or current axes
    """
        # from .../pylab_examples/ellipse_demo.py
    e = Circle( xy=xy, radius=radius )
    if ax is None:
        ax = pl.gca()  # ax = subplot( 1,1,1 )
    ax.add_artist(e)
    e.set_clip_box(ax.bbox)
    e.set_edgecolor( color )
    e.set_facecolor( facecolor )  # "none" not None
    e.set_alpha( alpha )

alt text

(The circles in the picture get squashed to ellipses because imshow aspect="auto" ).

Comments

9

Basend on the example of Gary Kerr and as proposed here one may create empty circles related to specified values with following code:

import matplotlib.pyplot as plt 
import numpy as np 
from matplotlib.markers import MarkerStyle

x = np.random.randn(60) 
y = np.random.randn(60)
z = np.random.randn(60)

g=plt.scatter(x, y, s=80, c=z)
g.set_facecolor('none')
plt.colorbar()
plt.show()

5 Comments

This is the essentially a complexified version the accepted answer…
From my point is it not. Using scatter plot with colors does not except facecolor="none" within the command. Therefor the subsequent removement of the facecolor is needed as described in the given link. Unfortunaly this complexified solution is needed to remove the facecolor in scatter plots with colorcoding.
The approach in this answer is indeed useful if one wants to update a graph that originally does not contain empty circles. However, the question about creating these circles directly, so the accepted solution is the way to go, as it does the same as this answer but directly, with no extraneous update of a first graph.
This "complexified version" worked for me when embedding the argument within .scatter() did not. For context, I was also applying a colormap (c=z, cmap='jet').
this was the only answer that actually worked for empty circles with different colors
6

In matplotlib 2.0 there is a parameter called fillstyle which allows better control on the way markers are filled. In my case I have used it with errorbars but it works for markers in general http://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.errorbar.html

fillstyle accepts the following values: [‘full’ | ‘left’ | ‘right’ | ‘bottom’ | ‘top’ | ‘none’]

There are two important things to keep in mind when using fillstyle,

1) If mfc is set to any kind of value it will take priority, hence, if you did set fillstyle to 'none' it would not take effect. So avoid using mfc in conjuntion with fillstyle

2) You might want to control the marker edge width (using markeredgewidth or mew) because if the marker is relatively small and the edge width is thick, the markers will look like filled even though they are not.

Following is an example using errorbars:

myplot.errorbar(x=myXval, y=myYval, yerr=myYerrVal, fmt='o', fillstyle='none', ecolor='blue',  mec='blue')

2 Comments

Good tip re controlling of the line widths! The markeredgewidth parameter is called linewidths in matplotlib 3.3.1. See up-to-date information in the documentation
Doesn't seem to work with scatter in 3.7.1: PathCollection.set() got an unexpected keyword argument 'fillstyle'
1

So I assume you want to highlight some points that fit a certain criteria. You can use Prelude's command to do a second scatter plot of the hightlighted points with an empty circle and a first call to plot all the points. Make sure the s paramter is sufficiently small for the larger empty circles to enclose the smaller filled ones.

The other option is to not use scatter and draw the patches individually using the circle/ellipse command. These are in matplotlib.patches, here is some sample code on how to draw circles rectangles etc.

Comments

0

In case you look for empty circle in the errorbar plot.

plt.errorbar(fmt='o', color='C0', mfc= "None") 

1 Comment

The question is not about error bars… How does this answer relate to the question exactly?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.