55

I'm trying to use matplotlib to make a scatter plot with very small gray points. Because of the point density, the points need to be small. The problem is that the scatter() function's markers seem to have both a line and a fill. When the markers are small, only the line is visible, not the fill, and the line isn't the right colour (it's always black).

I can get exactly what I want using gnuplot: plot 'nodes' with points pt 0 lc rgb 'gray'

How can I make very small gray points using matplotlib scatterplot()?

cyborg
  • 9,989
  • 4
  • 38
  • 56
zoo
  • 1,901
  • 1
  • 17
  • 25

4 Answers4

71
scatter([1,2,3], [2,4,5], s=1, facecolor='0.5', lw = 0)

This sets the markersize to 1 (s=1), the facecolor to gray (facecolor='0.5'), and the linewidth to 0 (lw=0).

Daan
  • 2,049
  • 14
  • 21
  • 7
    This works, but it's more general to set `edgecolor` to `''` for the reason the other answer mentions. – Matt Hall Mar 12 '15 at 16:52
  • 2
    Actually, in later versions of Matplotlib (as opposed to the one in vouge in 2011 when the question was asked), you can use the keyword 'color' which will set the edgecolor and facecolor simultaneously. This feature, however, is undocumented, suggested for depreciation, and conflicts with the behaviour for "plot", where 'color' will only set the linecolor and fillcolor, but not the edgecolor. – Daan Mar 13 '15 at 14:23
31

If the marker has no face (cannot be filled, e.g. '+','x'), then the edgecolor has to be set instead of c, and lw should not be 0:

scatter([1,2,3], [2,4,5], marker='+', edgecolor='r')

The following will no work

scatter([1,2,3], [2,4,5], s=1,  marker='+', facecolor='0.5', lw = 0)

because the edge/line will not be displayed, so nothing will be displayed.

cyborg
  • 9,989
  • 4
  • 38
  • 56
  • coloring the edge is a better solution than not showing it. hard to find as the matplotlib documentation mentions the incorrect "markeredgecolor" instead of the correct "edgecolor" – user989762 Aug 15 '13 at 10:27
  • 1
    When calling `plot.scatter` from a pandas DataFrame, neither `markeredgecolor` nor `edgecolor` seem valid parameters, as of december 2017. – bli Dec 08 '17 at 15:15
5

The absolute simplest answer to your question is: use the color parameter instead of the c parameter to set the color of the whole marker.

It's easy to see the difference when you compare the results:

from matplotlib import pyplot as plt

plt.scatter([1,2,3], [3,1,2], c='0.8')  # marker not all gray

plt.scatter([1,2,3], [3,1,2], color='0.8')  # marker all gray

Details: For your simple use case where you just want to make your whole marker be the same shade of gray color, you really shouldn't have to worry about things like face color vs edge color, and whether your marker is defined as all edges or some edges and some fill. Instead, just use the color parameter and know that your whole marker will be set to the single color that you specify!

qg_jinn
  • 71
  • 1
  • 5
  • This doesn't work when the color is a "sequence of values to be mapped" (i.e. not a fixed parameter but one of the variables you are plotting). You get an error message telling you very specifically to use 'c=' instead. Do you know how to get the effect of 'color=' when color is a variable? – zwol Aug 03 '16 at 14:10
1

In response to zwol's question in comment - my reputation is not high enough to leave comments, so this will have to do: In the event that your colors come from a colormap (i.e., are from a "sequence of values to be mapped") you can use color = as demonstrated in the following:

from matplotlib import pyplot

x = [1,5,8,9,5]
y = [4,2,4,7,9]
numSides = [2,3,1,1,5]

cmap = pyplot.cm.get_cmap("copper_r")

min, max = min(numSides), max(numSides)
for i in range(len(x)):
    if numSides[i] >= 2:
        cax = pyplot.scatter(x[i], y[i], marker = '+', s = 100, c = numSides[i], cmap = cmap)
        cax.set_clim(min, max)
    elif numSides[i] == 1:
        pyplot.scatter(x[i], y[i], marker = '.', s = 40, color = cmap(numSides[i]))

fig = pyplot.gcf()
fig.set_size_inches(8.4, 6)
fig.savefig('figure_test.png', dpi = 200)
pyplot.show()
marisano
  • 571
  • 6
  • 10