2016-04-18 16 views
6

Ho una nuvola di punti nello spazio tridimensionale e ho stimato una distribuzione su quei punti (anche nello spazio 3D, utilizzando kernel density estimation sebbene ciò sia irrilevante per questa domanda). Vorrei tracciare la proiezione di quella distribuzione come un contorno su tutti e tre gli assi (x, yez). È semplice fare questo per l'asse z (cioè progetto sull'aereo con la stessa coordinata z ovunque):Tracciare i contorni della distribuzione su tutti e tre gli assi nella trama 3D

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)) 

Projection of contours onto z-axis

Tuttavia, questa operazione per gli altri assi sembra non essere attuata in matplotlib. Se uso il metodo descritto nel this example, e specificare un argomento zdir parola chiave:

# 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') 

la generazione del contorno è fatto 'lungo un'altra fetta', per così dire:

enter image description here

Mentre voglio qualcosa di simile (competenze cattiva vernice; spero l'idea è chiara):

enter image description here

Un'opzione che avevo in mente era quella di generare il contorno lungo il default zdir='z' e quindi ruotare le curve risultanti nello spazio 3D, ma non ho idea di come affrontarlo. Sarei molto grato per qualsiasi suggerimento!

risposta

4

Ho provato a modificare i grafici di profilo mescolando i dati calcolati come somma lungo un asse con la griglia creata da np.mgrid. Ho calcolato la somma della densità lungo l'asse su cui voglio avere il contorno. Questo appare come segue:

# 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 

Purtroppo io non sono molto familiare con la stima della densità del kernel, quindi spero non ho capito qualcosa di completamente sbagliato, ma il risultato generato se si aggiungono le poche righe di codice di cui sopra sembra qualcosa simile alla tua immagine di pittura fantasia :) enter image description here

+0

Così semplice, mi sento stupido per non aver pensato a me stesso :) Ottima risposta; molte grazie! – EelkeSpaak

+0

Prego! Questi meshgrid necessari per il tracciamento 3D di matplotlib spesso confondono anche me stesso. Sono contento di sapere che potrei aiutarti! :) – jmartin

Problemi correlati