23

How can I create a 3D plot with a color gradient for the points? See the example below, which works for a 2D scatter plot.

Edit (thanks to Chris): What I'm expecting to see from the 3D plot is a color gradient of the points ranging from red to green as in the 2D scatter plot. What I see in the 3D scatter plot are only red points.

Solution: for some reasons (related to the gradient example I copied elsewhere) I set xrange to len-1, which messes everything in the 3D plot.

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Create Map
cm = plt.get_cmap("RdYlGn")

x = np.random.rand(30)
y = np.random.rand(30)
z = np.random.rand(30)
#col = [cm(float(i)/(29)) for i in xrange(29)] # BAD!!!
col = [cm(float(i)/(30)) for i in xrange(30)]

# 2D Plot
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(x, y, s=10, c=col, marker='o')  

# 3D Plot
fig = plt.figure()
ax3D = fig.add_subplot(111, projection='3d')
ax3D.scatter(x, y, z, s=10, c=col, marker='o')  

plt.show()
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
andrea.ge
  • 1,937
  • 1
  • 18
  • 27
  • What's wrong with the 3D scatter plot? What do you expect to see from it and what do you actually see? From you code your call to [`Axes3D.scatter`](http://matplotlib.sourceforge.net/mpl_toolkits/mplot3d/tutorial.html#scatter-plots) seems ok. – Chris Jan 17 '12 at 09:13
  • What I'm expecting to see from the 3D plot is a color gradient of the points ranging from red to green as in the 2D scatter plot. What I see in the 3D scatter plot are only red points. – andrea.ge Jan 17 '12 at 09:49
  • [Answer to a similar question](https://stackoverflow.com/a/49618481/3491991) – zelusp Apr 06 '18 at 21:17

2 Answers2

29

Here is an example for 3d scatter with gradient colors:

import matplotlib.cm as cmx
from mpl_toolkits.mplot3d import Axes3D
def scatter3d(x,y,z, cs, colorsMap='jet'):
    cm = plt.get_cmap(colorsMap)
    cNorm = matplotlib.colors.Normalize(vmin=min(cs), vmax=max(cs))
    scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=cm)
    fig = plt.figure()
    ax = Axes3D(fig)
    ax.scatter(x, y, z, c=scalarMap.to_rgba(cs))
    scalarMap.set_array(cs)
    fig.colorbar(scalarMap)
    plt.show()

Of course, you can choose the scale to range between different values, like 0 and 1.

Noam Peled
  • 4,484
  • 5
  • 43
  • 48
  • 3
    `ax.scatter(z, y, z, c=scalarMap.to_rgba(cs))` should be `ax.scatter(x, y, z, c=scalarMap.to_rgba(cs))` – orange Jan 09 '15 at 13:05
  • 6
    @NoamPeled What does `cs` mean? – Haozhe Xie Jan 21 '19 at 01:36
  • It's the values for each 3D point. If colors_data is a 3D matrix, with a value for each 3D point, X is a Nx3 matrix of list of x,y,z coordinates, so cs=[colors_data[x, y, z] for x,y,z in zip(X[:, 0], X[:, 1], X[:, 2])] – Noam Peled Jan 22 '19 at 02:45
  • @NoamPeled the 3d plot tends to alter the relative aspect ratio of the axes. Is it possible to prevent this? looks awkward if one of the dimensions is much larger than the other? – Alexander Cska Apr 04 '23 at 16:05
5

Following works: I can't figure out why yours doesn't. You should be able to set color as a sequence of RGBA floats, or just sequence of floats.

# Create Map
cm = plt.get_cmap("RdYlGn")

x = np.random.rand(30)
y = np.random.rand(30)
z = np.random.rand(30)
col = np.arange(30)

# 2D Plot
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(x, y, s=10, c=col, marker='o')  

# 3D Plot
fig = plt.figure()
ax3D = fig.add_subplot(111, projection='3d')
p3d = ax3D.scatter(x, y, z, s=30, c=col, marker='o')                                                                                

plt.show()

However, in help of scatter, I see the following, it may be related.

    A :class:`matplotlib.colors.Colormap` instance or registered
    name. If *None*, defaults to rc ``image.cmap``. *cmap* is
    only used if *c* is an array of floats.
Cenkoloji
  • 93
  • 1
  • 5
  • 2
    Adding ", cmap=cm" (ax3D.scatter(x, y, z, s=30, c=col, marker='o', cmap=cm)) to the scatter function I have the color gradient back also in the 3D scatter plot. What I miss now seems to be the depth, but I guess I can not have both. – andrea.ge Jan 17 '12 at 10:16
  • what do you mean you don't have depth? – Cenkoloji Jan 17 '12 at 15:02