Graphs of distribution contours along all three axes in 3D-graphics

I have a cloud of points in three-dimensional space and some distribution over these points is estimated (also in three-dimensional space, using the kernel density estimate although this does not matter for this question). I would like to construct a projection of this distribution in the form of a contour on all three axes (x, y and z). This is easy to do for the z axis (i.e. Projection onto a plane with the same z-coordinate everywhere):

import numpy as np import scipy as sp import scipy.stats import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import axes3d # generate some points of a 3D Gaussian points = np.random.normal(size=(3, 50)) # do kernel density estimation to get smooth estimate of distribution # make grid of points x, y, z = np.mgrid[-4:4:100j, -4:4:100j, -4:4:100j] kernel = sp.stats.gaussian_kde(points) positions = np.vstack((x.ravel(), y.ravel(), z.ravel())) density = np.reshape(kernel(positions).T, x.shape) # now density is 100x100x100 ndarray # plot points ax = plt.subplot(projection='3d') ax.plot(points[0,:], points[1,:], points[2,:], 'o') # plot projection of density onto z-axis plotdat = np.sum(density, axis=2) plotdat = plotdat / np.max(plotdat) plotx, ploty = np.mgrid[-4:4:100j, -4:4:100j] ax.contour(plotx, ploty, plotdat, offset=-4) ax.set_xlim((-4, 4)) ax.set_ylim((-4, 4)) ax.set_zlim((-4, 4)) 

Projecting contours on the z axis

However, doing this for other axes does not seem to be implemented in Matplotlib. If I use the method described in this example , and specify the zdir keyword argument:

 # plot projection of density onto x-axis plotdat = np.sum(density, axis=0) plotdat = plotdat / np.max(plotdat) ploty, plotz = np.mgrid[-4:4:100j, -4:4:100j] ax.contour(ploty, plotz, plotdat, offset=-4, zdir='x') 

contour generation is performed โ€œalong another sliceโ€, so to speak:

enter image description here

While I want something like this (bad drawing skills, hope the idea is clear):

enter image description here

One option that I had in mind was to create a default zdir='z' , and then rotate the resulting curves in 3D space, but I have no idea how to approach this. I would really appreciate any pointers!

+6
source share
1 answer

I tried to change the contour graphs by mixing the data calculated as the sum along the axis with the grid created by np.mgrid . I calculated the sum of the density along the axis on which I want to have a path. It looks like this:

 # plot projection of density onto z-axis plotdat = np.sum(density, axis=2) plotdat = plotdat / np.max(plotdat) plotx, ploty = np.mgrid[-4:4:100j, -4:4:100j] ax.contour(plotx, ploty, plotdat, offset=-4, zdir='z') #This is new #plot projection of density onto y-axis plotdat = np.sum(density, axis=1) #summing up density along y-axis plotdat = plotdat / np.max(plotdat) plotx, plotz = np.mgrid[-4:4:100j, -4:4:100j] ax.contour(plotx, plotdat, plotz, offset=4, zdir='y') #plot projection of density onto x-axis plotdat = np.sum(density, axis=0) #summing up density along z-axis plotdat = plotdat / np.max(plotdat) ploty, plotz = np.mgrid[-4:4:100j, -4:4:100j] ax.contour(plotdat, ploty, plotz, offset=-4, zdir='x') #continue with your code 

Unfortunately, I am not very familiar with estimating the kernel density, so I hope I didnโ€™t understand something completely wrong, but the result generated by adding a few lines of code above looks something like your imaginary paint image :) enter image description here

+4
source

All Articles