2016-04-18 26 views
6

Mam chmurę punktów w przestrzeni trójwymiarowej i oszacowałem pewien rozkład w tych punktach (także w przestrzeni 3D, używając kernel density estimation, chociaż nie ma to znaczenia dla tego pytania). Chciałbym narysować rzut tego rozkładu jako wykres konturu na wszystkie trzy osie (x, yi z). Jest to proste do zrobienia tego dla osi (czyli projektu na płaszczyźnie z samym współrzędna wszędzie):Obrys konturów rozkładu we wszystkich trzech osiach na wykresie 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

Jednak robi to dla innych osi wydaje się nie być realizowane w Matplotlib. Gdybym zastosować metodę opisaną w this example i określić argument zdir kluczowe:

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

generowanie konturu odbywa się „wzdłuż innego wycinka”, że tak powiem:

enter image description here

co następuje: Chcę coś jak to (umiejętności złe malowania; nadzieję, że pomysł jest jasne):

enter image description here

Jedną z opcji, którą miałem na myśli było wygenerowanie konturu wzdłuż domyślnego zdir='z', a następnie obracanie wynikowych krzywych w przestrzeni 3D, ale nie mam pojęcia, jak do tego podejść. Byłbym bardzo wdzięczny za wszelkie wskazówki!

Odpowiedz

4

Próbowałem zmodyfikować wykresy konturu, mieszając dane obliczone jako suma wzdłuż osi z siatką utworzoną przez np.mgrid. Obliczyłem sumę gęstości wzdłuż osi, na której chcę obrysować kontur. Wygląda to następująco:

# 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 

Niestety nie jestem bardzo obeznany z estymacji gęstości jądra, więc mam nadzieję, że nie rozumiał zupełnie coś złego, ale wynik generowany jeśli dodać kilka linijek kodu powyżej wygląda mniej podobna do twojej wyobraźni obrazka :) enter image description here

+0

Tak prosty, czuję się głupio, że o tym nie myślałam :) Doskonała odpowiedź; wielkie dzięki! – EelkeSpaak

+0

Nie ma za co! Siatki te, które są potrzebne do renderowania 3D przez Matplotlib, często również wprowadzają w błąd. Cieszę się, że mogę ci pomóc! :) – jmartin