23

I'm trying to show a color bar of my scatter plot but I'm keep getting the error:

TypeError: You must first set_array for mappable

This is what I'm doing to plot:

# Just plotting the values of data that are nonzero 
x_data = numpy.nonzero(data)[0] # x coordinates
y_data = numpy.nonzero(data)[1] # y coordinates

# Mapping the values to RGBA colors
data = plt.cm.jet(data[x_data, y_data])

pts = plt.scatter(x_data, y_data, marker='s', color=data)

plt.colorbar(pts)

If I comment the line plt.colorbar(pts) I got the plot correctly, but I would like to plot the color bar too.

Thank you in advance.

pceccon
  • 9,379
  • 26
  • 82
  • 158

1 Answers1

15

You're passing in specific rgb values, so matplotlib can't construct a colormap, because it doesn't know how it relates to your original data.

Instead of mapping the values to RGB colors, let scatter handle that for you.

Instead of:

# Mapping the values to RGBA colors
data = plt.cm.jet(data[x_data, y_data])

pts = plt.scatter(x_data, y_data, marker='s', color=data)

Do:

pts = plt.scatter(x_data, y_data, marker='s', c=data[x_data, y_data])

(Just pass in to c what you were originally passing into plt.cm.jet.)

Then you'll be able to construct a colormap normally. The specific error is telling you that the colors have been manually set, rather than set through set_array (which handles mapping an array of data values to RGB).

Joe Kington
  • 275,208
  • 71
  • 604
  • 463
  • It worked. I just have one last question.. I have tried this using color=data[x_data, y_data], and I got the same error message. So, c != color? Thank you, @JoeKington. (: – pceccon Jul 18 '14 at 20:26
  • 1
    No, `color` is an alias for `facecolors`. (This is a bit confusing, but it's due to inheriting matlab's plotting api.) `c` is a carryover from the original matlab's scatter. `scatter` is intended to be called as `scatter(x, y, c=z1, s=z1)` to simultaneously display 4 variables. (Two positions, vary by color, and vary by size). Behind the scenes, `color` calls `set_facecolors` and `c` calls `set_array` on the output collection. In the long run, it's probably a good idea to make `color` behave identically to `c` if a scalar array is passed in. – Joe Kington Jul 18 '14 at 20:28
  • Huuum, understood. (: However, my colors get pretty different (and I got squares with white contours) from the other plot, even if I passe the argument cmap=plt.cm.jet. – pceccon Jul 18 '14 at 20:30
  • 1
    @pceccon - Yep! That's because in your original example, the range of the data was being scaled between 0 and 1, while in my example, it's being scaled between the min and max of the data. To make it identical to the original, use `cmin=0, cmax=1`. – Joe Kington Jul 18 '14 at 20:31
  • Right! Glad you caught that! – Joe Kington Jul 18 '14 at 20:34