How do I build a projection of three-dimensional scattering data on the XY / XZ / YZ planes?

I have 4D data (3D scatter points + color) built using the matplotlib mplot3d library. To help understand how a point cloud is distributed in space, I would like to show the projection of the cloud on each of the three planes (XY, XZ, YZ) using a 2D histogram / contour plot.

Here is the MWE that uses ax.plot to accomplish what I want (from the link below). This technically works, but I think replacing the bike-shot from ax.plot contour plots would be more enjoyable:

 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # Prepare sample data - normally distributed NSamples = 5000 vmin, vmax = -2, 2 X = np.random.normal(loc=-.1, scale=.5, size=(NSamples,)) Y = np.random.normal(loc=.1, scale=.25, size=(NSamples,)) Z = np.random.normal(loc=0, scale=1, size=(NSamples,)) # Create figure, add subplot with 3d projection fig = plt.figure(figsize=(5,5)) ax = fig.add_subplot(111, projection='3d') ax.set_xlabel("X") ax.set_ylabel("Y") ax.set_zlabel("Z") ax.set_xlim(vmin, vmax) ax.set_ylim(vmin, vmax) ax.set_zlim(vmin, vmax) # Plot the data cloud ax.scatter(X, Y, Z, s=.5, alpha=.05, color='k') # Plot the 2D projections using `plot`. This is the piece I'd like to improve ax.plot(X, Y, '+', markersize=.2, color='r', zdir='z', zs=-2.) ax.plot(X, Z, '+', markersize=.2, color='g', zdir='y', zs=2.) ax.plot(Y, Z, '+', markersize=.2, color='b', zdir='x', zs=-2.) plt.savefig("3DScatter.png") # Now, I'd *like* for the following histograms to be plotted on each of the XY, XZ, YZ planes instead of using `plot` above for label, data_x, data_y in [ ['XY', X, Y], ['XZ', X, Z], ['YZ', Y, Z] ]: hist, binx, biny = np.histogram2d( data_x, data_y, bins=[xbins, ybins]) plt.figure(figsize=(5,5)) plt.imshow(hist, extent=[vmin,vmax,vmin,vmax]) plt.xlabel(label[1]) 

What produces:

3D scatterXy

XzYz

and etc.

So, to make it clear, is there a way to plot the XY, XZ, YZ 2D imshow using imshow above on connected 3D axes? A contour based solution would also be great.

Please note that (I'm pretty sure) this is not a repetition of this related question , the solution of which works only for 2D data (f (x, y)), not 3D (f (x, y, z)).

+6
source share
1 answer

If you use contour or contourf , you can do something like this:

 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # Prepare sample data - normally distributed NSamples = 5000 vmin, vmax = -2, 2 X = np.random.normal(loc=-.1, scale=.5, size=(NSamples,)) Y = np.random.normal(loc=.1, scale=.25, size=(NSamples,)) Z = np.random.normal(loc=0, scale=1, size=(NSamples,)) # Create figure, add subplot with 3d projection fig = plt.figure(figsize=(5,5)) ax = fig.add_subplot(111, projection='3d') ax.set_xlabel("X") ax.set_ylabel("Y") ax.set_zlabel("Z") ax.set_xlim(vmin, vmax) ax.set_ylim(vmin, vmax) ax.set_zlim(vmin, vmax) # Plot the data cloud ax.scatter(X, Y, Z, s=.5, alpha=.05, color='k') hist, binx, biny = np.histogram2d( X, Y) x = np.linspace(X.min(), X.max(), hist.shape[0]) y = np.linspace(Y.min(), Y.max(), hist.shape[1]) x, y = np.meshgrid(x, y) ax.contour(x, y, hist, zdir='z', offset=-3.) hist, binx, biny = np.histogram2d( X, Z) x = np.linspace(X.min(), X.max(), hist.shape[0]) z = np.linspace(Z.min(), Z.max(), hist.shape[1]) x, z = np.meshgrid(x, z) ax.contour(x, hist, z, zdir='y', offset=3) hist, binx, biny = np.histogram2d( Y, Z) y = np.linspace(Y.min(), Y.max(), hist.shape[0]) z = np.linspace(Z.min(), Z.max(), hist.shape[1]) z, y = np.meshgrid(z, y) ax.contour(hist, y, z, zdir='x', offset=-3) ax.set_xlim([-3, 3]) ax.set_ylim([-3, 3]) ax.set_zlim([-3, 3]) 
+4
source

Source: https://habr.com/ru/post/987387/


All Articles