Plotting 3D scatter with python? - python

Is there any module that could aid me in producing something like this?

Like this, say?
(source: sourceforge.net)
The matplotlib examples gallery is a wonderful thing to behold.
Code copied from the linked example.
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
def randrange(n, vmin, vmax):
return (vmax-vmin)*np.random.rand(n) + vmin
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
n = 100
for c, m, zl, zh in [('r', 'o', -50, -25), ('b', '^', -30, -5)]:
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, zl, zh)
ax.scatter(xs, ys, zs, c=c, marker=m)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()

Adapted from the Cookbook
from numpy import *
import pylab as p
import mpl_toolkits.mplot3d.axes3d as p3
x=random.randn(100)
y=random.randn(100)
z=random.randn(100)
fig=p.figure()
ax = p3.Axes3D(fig)
ax.scatter3D(ravel(x),ravel(y),ravel(z))
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
p.show()

I think matplotlib should be able to do something like that.

Related

Matplotlib overlapping color and marker

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for color, marker in [('g', 'x'), ('r', 'o'), ('b', '^')]:
ax.scatter(x[:100],y[:100],z[:100], marker=marker, color=color, s=50, alpha=.3)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
gets me this
but I want this instead
I tried changing facecolor and edgecolor but no help.
The tutorial code seems to work the way I want and doesn't overlap the markers and gets the colors correct. Is there an easier way to do this without the loop?
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
def randrange(n, vmin, vmax):
return (vmax - vmin)*np.random.rand(n) + vmin
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
n = 100
for c, m, zl, zh in [('g', 'o', -50, -25), ('b', '^', -30, -5), ('r', 'x', -30, -5)]:
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, zl, zh)
ax.scatter(xs, ys, zs, edgecolor=(0,0,0,0), c=c, marker=m)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()

3dplot scatter points via python

I just used numpy.loadtxt('filename', usecols=(0,)) to load a csv with the following format:
x,y,z
1.1,2.2,3.3
5.5,1.45,6.77
(There are ~1M lines). I'd like to make a scatterplot. I searched the web and found numpy.meshgrid and mlab.surf but I'm not sure what to do. Please point me in the right direction.
I think you can use matplotlib, it's very powerful, and widely used, most importantly, it has good document and is easy to use.
Hope helps!
There is a very simple example from here.
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
def randrange(n, vmin, vmax):
return (vmax-vmin)*np.random.rand(n) + vmin
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
n = 100
for c, m, zl, zh in [('r', 'o', -50, -25), ('b', '^', -30, -5)]:
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, zl, zh)
ax.scatter(xs, ys, zs, c=c, marker=m)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
You just need to parse your data instead of using randrange.

How to plot heatmap colors in 3D in Matplotlib

I am using Matplotlib 3D to plot 3 dimensions of my dataset like below:
But now I also want to visualize a 4th dimension (which is a scalar value between 0 to 20) as a heatmap. So basically, I want each point to take it's color based on this 4th dimension's value.
Is there such a thing exists in Matplotlib? How can I convert a bunch of numbers between [0-20] to heatmap colors?
I took the code from here: http://matplotlib.org/mpl_examples/mplot3d/scatter3d_demo.py
Yes, something like this:
update here is a version with a colorbar.
import numpy as np
from pylab import *
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
def randrange(n, vmin, vmax):
return (vmax-vmin)*np.random.rand(n) + vmin
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(111,projection='3d')
n = 100
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, 0, 100)
colmap = cm.ScalarMappable(cmap=cm.hsv)
colmap.set_array(zs)
yg = ax.scatter(xs, ys, zs, c=cm.hsv(zs/max(zs)), marker='o')
cb = fig.colorbar(colmap)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
looks like:
update Here is an explicit example of coloring your data points by some 4th dimensional attribute.
import numpy as np
from pylab import *
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
def randrange(n, vmin, vmax):
return (vmax-vmin)*np.random.rand(n) + vmin
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(111,projection='3d')
n = 100
xs = randrange(n, 0, 100)
ys = randrange(n, 0, 100)
zs = randrange(n, 0, 100)
the_fourth_dimension = randrange(n,0,100)
colors = cm.hsv(the_fourth_dimension/max(the_fourth_dimension))
colmap = cm.ScalarMappable(cmap=cm.hsv)
colmap.set_array(the_fourth_dimension)
yg = ax.scatter(xs, ys, zs, c=colors, marker='o')
cb = fig.colorbar(colmap)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
I mostly agree with #seth but I would like to change 1 line so that the color values are not normalized:
yg = ax.scatter(xs, ys, zs, c=colmap.to_rgba(the_fourth_dimension)[:,0,0:3], marker='o')

Matplotlib 3D Scatter Plot with Colorbar

Borrowing from the example on the Matplotlib documentation page and slightly modifying the code,
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
def randrange(n, vmin, vmax):
return (vmax-vmin)*np.random.rand(n) + vmin
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
n = 100
for c, m, zl, zh in [('r', 'o', -50, -25), ('b', '^', -30, -5)]:
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, zl, zh)
cs = randrange(n, 0, 100)
ax.scatter(xs, ys, zs, c=cs, marker=m)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
Will give a 3D scatter plot with different colors for each point (random colors in this example). What's the correct way to add a colorbar to the figure, since adding in plt.colorbar() or ax.colorbar() doesn't seem to work.
This produces a colorbar (though possibly not the one you need):
Replace this line:
ax.scatter(xs, ys, zs, c=cs, marker=m)
with
p = ax.scatter(xs, ys, zs, c=cs, marker=m)
then use
fig.colorbar(p)
near the end
Using the above answer did not solve my problem. The colorbar colormap was not linked to the axes (note also the incorrect colorbar limits):
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
data = np.random.rand(3, 100)
x, y, z = data # for show
c = np.arange(len(x)) / len(x) # create some colours
p = ax.scatter(x, y, z, c=plt.cm.magma(0.5*c))
ax.set_xlabel('$\psi_1$')
ax.set_ylabel('$\Phi$')
ax.set_zlabel('$\psi_2$')
ax.set_box_aspect([np.ptp(i) for i in data]) # equal aspect ratio
fig.colorbar(p, ax=ax)
The solution (see here also) is to use cmap in ax.scatter:
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
data = np.random.rand(3, 100)
x, y, z = data # for show
c = np.arange(len(x)) / len(x) # create some colours
p = ax.scatter(x, y, z, c=0.5*c, cmap=plt.cm.magma)
ax.set_xlabel('$\psi_1$')
ax.set_ylabel('$\Phi$')
ax.set_zlabel('$\psi_2$')
ax.set_box_aspect([np.ptp(i) for i in data]) # equal aspect ratio
fig.colorbar(p, ax=ax)

Any easy way to plot a 3d scatter in Python that I can rotate around?

Currently I'm using matplotlib to plot a 3d scatter and while it gets the job done, I can't seem to find a way to rotate it to see my data better.
Here's an example:
import pylab as p
import mpl_toolkits.mplot3d.axes3d as p3
#data is an ndarray with the necessary data and colors is an ndarray with
#'b', 'g' and 'r' to paint each point according to its class
...
fig=p.figure()
ax = p3.Axes3D(fig)
ax.scatter(data[:,0], data[:,2], data[:,3], c=colors)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
fig.add_axes(ax)
p.show()
I'd like a solution that lets me do it during execution time but as long as I can rotate it and it's short/quick I'm fine with it.
Here's a comparison of the plots produced after applying a PCA to the iris dataset:
1. mayavi
2. matplotlib
Mayavi makes it easier to visualize the data, but MatPlotLib looks more professional. Matplotlib is also lighter.
Well, first you need to define what you mean by "see my data better"...
You can rotate and zoom in on the plot using the mouse, if you're wanting to work interactively.
If you're just wanting to rotate the axes programatically, then use ax.view_init(elev, azim) where elev and azim are the elevation and azimuth angles (in degrees) that you want to view your plot from.
Alternatively, you can use the ax.elev, ax.azim, and ax.dist properties to get/set the elevation, azimuth, and distance of the current view point.
Borrowing the source from this example:
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
def randrange(n, vmin, vmax):
return (vmax-vmin)*np.random.rand(n) + vmin
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
n = 100
for c, m, zl, zh in [('r', 'o', -50, -25), ('b', '^', -30, -5)]:
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, zl, zh)
ax.scatter(xs, ys, zs, c=c, marker=m)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
We get a nice scatterplot:
You can rotate the axes programatically as shown:
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
def randrange(n, vmin, vmax):
return (vmax-vmin)*np.random.rand(n) + vmin
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
n = 100
for c, m, zl, zh in [('r', 'o', -50, -25), ('b', '^', -30, -5)]:
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, zl, zh)
ax.scatter(xs, ys, zs, c=c, marker=m)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
ax.azim = 200
ax.elev = -45
plt.show()
Hope that helps a bit!
Using mayavi, you can create such a plot with
import enthought.mayavi.mlab as mylab
import numpy as np
x, y, z, value = np.random.random((4, 40))
mylab.points3d(x, y, z, value)
mylab.show()
The GUI allows rotation via clicking-and-dragging, and zooming in/out via right-clicking-and-dragging.

Categories