22

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()
andrea.ge
  • 1,897
  • 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

28

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,186
  • 3
  • 41
  • 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
  • 4
    @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
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
  • 1
    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