2015-05-17 7 views
6

Mam dane 4D (punkty rozproszenia 3D + kolor) wykreślone przy użyciu biblioteki mplot3d matplotlib. Aby pomóc w analizie rozkładu chmur punktów w przestrzeni, chciałbym wyświetlić rzut chmurki na każdą z 3 płaszczyzn (XY, XZ, YZ) za pomocą histogramu 2D/wykresu konturu.Jak wykreślić rzut 3D danych rozproszenia na płaszczyznach XY/XZ/YZ?

Oto MWE, który używa ax.plot do zrobienia tego, co chcę (za link poniżej). To technicznie działa, ale myślę, zastępując Buck-strzał z ax.plot z działek konturu będzie bardziej wizualnie miłe:

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

która produkuje:

3D scatterXY

XZYZ

itp.

Tak, aby być czystym r, czy istnieje sposób na wykreślenie histogramów XY, XZ, YZ 2D wykreślonych powyżej z imshow na powiązanych osiach 3D? Rozwiązanie oparte na contour również byłoby w porządku.

Zauważ, że (jestem dość pewny) to nie powtórzenie this related question, którego rozwiązanie działa tylko dla danych 2D (F (x, y)), nie 3D (f (x, y, z)).

Odpowiedz

4

Jeśli są w porządku z użyciem contour lub contourf, można zrobić coś takiego:

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]) 
+0

Przysięgam, że próbowała właśnie to rozwiązanie, ale wyraźnie nie. Zajrzyj do mojej poprzedniej wersji, gdzie popełniłem błąd. Działa to dokładnie zgodnie z przeznaczeniem, dziękuję! – paradiso

+0

Nie ma za co :-) –

Powiązane problemy