pylab 3d scatter plots with 2d projections of plotted data - python

I am trying to create a simple 3D scatter plot but I want to also show a 2D projection of this data on the same figure.
This would allow to show a correlation between two of those 3 variables that might be hard to see in a 3D plot.
I remember seeing this somewhere before but was not able to find it again.
Here is some toy example:
x= np.random.random(100)
y= np.random.random(100)
z= sin(x**2+y**2)
fig= figure()
ax= fig.add_subplot(111, projection= '3d')
ax.scatter(x,y,z)

You can add 2D projections of your 3D scatter data by using the plot method and specifying zdir:
import numpy as np
import matplotlib.pyplot as plt
x= np.random.random(100)
y= np.random.random(100)
z= np.sin(3*x**2+y**2)
fig= plt.figure()
ax= fig.add_subplot(111, projection= '3d')
ax.scatter(x,y,z)
ax.plot(x, z, 'r+', zdir='y', zs=1.5)
ax.plot(y, z, 'g+', zdir='x', zs=-0.5)
ax.plot(x, y, 'k+', zdir='z', zs=-1.5)
ax.set_xlim([-0.5, 1.5])
ax.set_ylim([-0.5, 1.5])
ax.set_zlim([-1.5, 1.5])
plt.show()

The other answer works with matplotlib 0.99, but 1.0 and later versions need something a bit different (this code checked with v1.3.1):
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
x= np.random.random(100)
y= np.random.random(100)
z= np.sin(3*x**2+y**2)
fig= plt.figure()
ax = Axes3D(fig)
ax.scatter(x,y,z)
ax.plot(x, z, 'r+', zdir='y', zs=1.5)
ax.plot(y, z, 'g+', zdir='x', zs=-0.5)
ax.plot(x, y, 'k+', zdir='z', zs=-1.5)
ax.set_xlim([-0.5, 1.5])
ax.set_ylim([-0.5, 1.5])
ax.set_zlim([-1.5, 1.5])
plt.show()
You can see what version of matplotlib you have by importing it and printing the version string:
import matplotlib
print matplotlib.__version__

Related

How to use np.arange() to create a 3D scatter plot

I'm trying to recreate a 3D scatter plot figure but I'm having a hard time with getting the range right on the y axis.
This is the figure that I am trying to emulate:
Here's my code for the np.arange():
from mpl_toolkits import mplot3d
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=[15,15])
z = 520 * np.random.random(100)
x = np.arange(0,20,0.2)
y = np.arange(0,20,0.2)
ax3 = fig.add_subplot(2,2,3, projection='3d')
ax3.set_xlabel('x', c='r', size=14)
ax3.set_ylabel('y', c='r', size=14)
ax3.set_zlabel('z', c='r', size=14)
ax3.scatter3D(x,y,z, c=z, cmap='jet')
ax3.view_init(25,45);
This is the output:
I'm not trying to make it look exactly the same with the angle but I need to get the axis plots correct.

2D line not showing clearly along with surface on 3D plot

I am trying to plot a 1D line along with a 2D surface in matplotlib with Axes3D:
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(-1., 1.1, 0.1)
y = x.copy()
X, Y = np.meshgrid(x, y)
Z = np.abs(X) + np.abs(Y)
plt.close('all')
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(np.zeros_like(y), y, 1, color='k')
ax.plot(x, np.zeros_like(x), 1, color='k')
surf = ax.plot_surface(X, Y, Z, color='w')
plt.show(block=False)
but the 2D plot somehow hides the lines:
If I comment the surf = plot_surface(...) code line, the 1D lines show correctly:
How can I have the lines showing correctly along with the surface?
Axes3D.plot_surface() apparently accepts a transparency (alpha) argument, which actually gets forwarded to a base class, Poly3DCollection.
And of course the line plot() calls accept a linewidth argument.
So if you render the line plots with thicker lines and you render the surface with some transparency, you should be able to find a combination of settings which let you see both the lines and the surface in a balanced way.
https://matplotlib.org/tutorials/toolkits/mplot3d.html#mpl_toolkits.mplot3d.Axes3D.plot_surface
https://matplotlib.org/api/_as_gen/mpl_toolkits.mplot3d.art3d.Poly3DCollection.html#mpl_toolkits.mplot3d.art3d.Poly3DCollection
You can also achieve this by using the zorder in the plot_surface and plot commands to make the lines sit on top of the surface. E.g.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(-1., 1.1, 0.1)
y = x.copy()
X, Y = np.meshgrid(x, y)
Z = np.abs(X) + np.abs(Y)
plt.close('all')
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, color='w', zorder=1)
ax.plot(np.zeros_like(y), y, 1, color='k', zorder=10)
ax.plot(x, np.zeros_like(x), 1, color='k', zorder=11)
plt.show(block=False)

How to set title position inside graph in scatter plot?

MWE:
I would like the title position same as in the graph :
Here is my code :
import matplotlib.pyplot as plt
import numpy as np
import random
fig, ax = plt.subplots()
x = random.sample(range(256),200)
y = random.sample(range(256),200)
cor=np.corrcoef(x,y)
plt.scatter(x,y, color='b', s=5, marker=".")
#plt.scatter(x,y, label='skitscat', color='b', s=5, marker=".")
ax.set_xlim(0,300)
ax.set_ylim(0,300)
plt.xlabel('x')
plt.ylabel('y')
plt.title('Correlation Coefficient: %f'%cor[0][1])
#plt.legend()
fig.savefig('plot.png', dpi=fig.dpi)
#plt.show()
But this gives :
How do I fix this title position?
assign two corresponded value to X and Y axis. notice! to have title inside graph, values should be in (0,1) interval. you can see a sample code here:
import matplotlib. pyplot as plt
A= [2,1,4,5]; B = [3,2,-2,1]
plt.scatter(A,B)
plt.title("title", x=0.9, y=0.9)
plt.xlabel("x-axis")
plt.ylabel("y-axis")
plt.show()
It will be unnecessarily complicated to move the title at some arbitrary position inside the axes.
Instead one would rather create a text at the desired position.
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
x = np.random.randint(256,size=200)
y = np.random.randint(256,size=200)
cor=np.corrcoef(x,y)
ax.scatter(x,y, color='b', s=5, marker=".")
ax.set_xlim(0,300)
ax.set_ylim(0,300)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.text(0.9, 0.9, 'Correlation Coefficient: %f'%cor[0][1],
transform=ax.transAxes, ha="right")
plt.show()

Plotting streamlines in a Matplotlib 3Dplot?

I'm trying to plot streamlines on a plane in a 3D plot using Matplotlib. For the streamlines, I'd like to use the function streamplot(), because of its simplicity. Here's a MWE that I modified from the gallery (to attempt the streamplot() call):
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
X, Y, Z = axes3d.get_test_data(0.05)
fig = plt.figure()
ax = fig.gca()
plt.streamplot(X, Y, X, Y)
plt.show()
fig = plt.figure()
ax = fig.gca(projection='3d')
cset = ax.contour(X, Y, Z, zdir='z', offset=-10, cmap=cm.coolwarm)
ax.set_zlim(-100, 100)
plt.show()
fig = plt.figure()
ax = fig.gca(projection='3d')
cset = ax.streamplot(X, Y, X, Y, zdir='z', offset=-10, cmap=cm.coolwarm)
ax.set_zlim(-100, 100)
plt.show()
The first and second examples work as intended, however, the third example gives me this error:
TypeError: streamplot() got an unexpected keyword argument 'zdir'
which hints to the possibility of this not being implemented. If I check Axes3D, the function streamplot() I get:
In [28]: Axes3D.streamplot
Out[28]: <function matplotlib.axes._axes.Axes.streamplot>
From which we get that streamplot() is the 2D version, and hence can't be directly used in 3D plots.
Is there a way to circumvent this and get a streamlines plane in a 3D plot?

mplot3d: how to show the ticks but not the grids?

I want to show the axis ticks with matplotlib/mplot3d but not the faint grids on the x/y/z background:
Is there a way to suppress the grids?
Calling ax.grid(False) should suffice. Self contained example, adding that line to this:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.grid(False)
X, Y, Z = axes3d.get_test_data(0.05)
ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
plt.show()

Categories