2015-05-17 7 views
6

Ich habe 4D Daten (3D Scatter Punkte + Farbe) geplottet mit Matplotlib mplot3d Bibliothek. Um zu analysieren, wie die Punktwolke im Raum verteilt ist, möchte ich eine Projektion der Wolke über jede der drei Ebenen (XY, XZ, YZ) mit Hilfe eines 2D-Histogramms/Konturdiagramms zeigen.Wie zeichne ich eine Projektion von 3D-Streudaten auf den XY/XZ/YZ-Ebenen?

Hier ist ein MWE, der ax.plot verwendet, um zu tun, was ich will (per den Link unten). Dies funktioniert technisch, aber ich denke, den Buck-Schuss von ax.plot mit der Kontur-Plots zu ersetzen wäre optisch ansprechend:

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

Welche produziert:

3D scatterXY

XZYZ

usw.

So zu clea r, gibt es eine Möglichkeit, die XY-, XZ-, YZ-2D-Histogramme, die oben mit imshow gezeichnet wurden, auf den zugehörigen 3D-Achsen darzustellen? Eine auf contour basierende Lösung wäre ebenfalls in Ordnung.

Beachten Sie, dass (ich bin ziemlich sicher) ist dies nicht eine Wiederholung von this related question, deren Lösung funktioniert nur für 2D-Daten (f (x, y)), nicht 3D (f (x, y, z)).

Antwort

4

Wenn Sie sind in Ordnung mit der Verwendung von contour oder contourf, können Sie etwas tun:

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

Ich schwöre, dass ich genau diese Lösung versucht, aber klar habe ich nicht. Ein Blick in meine vorherige Version, wo ich falsch gelaufen bin. Das funktioniert genauso wie beabsichtigt, danke! – paradiso

+0

Gern geschehen :-) –

Verwandte Themen