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.
Related
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()
I have a matplotlib figure that I want to be able to switch between 2D and 3D projections. I can go from 2D to 3D but I can't seem to work out how to go the other way. 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()
# Create a 3D scatter plot...
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')
# Now I want a 2D plot...
ax.cla()
ax = fig.add_subplot(111)
ax.plot(xs, ys)
plt.show()
The plot stays in the 3D projection and projection="2D" isn't a valid kwarg...
I thought perhaps ax.clf() would do what I wanted and let me define a new figure. But it just gives me the following error:
ValueError: Unknown element o
Can anyone give me a hint as to the solution to this? Is the ValueError related to the problem or a hint to something else wrong with my setup? Is there a kwarg to switch the projection from 3D to 2D?
Many thanks in advance for any pointer you can provide.
Dan
Let me start out by saying that if you boosted your acceptance rate (which is currently 0%) by going and demarcating the answers from your previous questions that you actually used, then perhaps more people would be willing to help you.
Now, to answer your question, there is no '2d' projection kwarg. However, if you want to go through and quickly decide which type of projection you would like, depending on a keyword 'q', the following should help you. I also altered the basic setup to avoid confusion between your different kinds of plots, since you had some plotting calls outside of the loop, and generally clean up your organization.
Hope this helps.
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()
plt.clf()
q='2d'
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)
if q=='3d':
# Create a 3D scatter plot...
ax = fig.add_subplot(111, projection='3d')
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()
else:
plt.clf()
ax = fig.add_subplot(111)
ax.plot(xs, ys)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
plt.show()
I believe I have found one possible solution, although it seems to result in a bit of a memory issue. I suspect that it isn't actually deleting the initial plot data, just removing it from the figure so memory usage does climb every time the projection is changed.
# Delete the 3D subplot
self.fig.delaxes(self.axes)
# Create a new subplot that is 2D
self.axes = self.fig.add_subplot(111)
# 2D scatter
self.axes.plot(10*np.random.randn(100), 10*np.random.randn(100), 'o')
# Update the figure
self.canvas.draw()
I was having the same problem and tried the accepted solution (posted by Dan). It worked, but gave me the following warning:
"UserWarning: This figure includes Axes that are not compatible with
tight_layout, so its results might be incorrect."
However if I use:
self.figure.clf()
self.axes = self.figure.add_subplot(111)
then it works without any warnings.
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)
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.
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.