3D bar plot

Du hast eine Idee für ein Projekt?
Antworten
BennyS
User
Beiträge: 19
Registriert: Montag 28. November 2016, 13:36

Hallo zusammen!:)
Ich hätte eine Frage an euch, ich habe das auch bereits gegoogled aber konnte anhand des gefundenen irgendwie trotzdem nicht hinter die thematik steigen.
Ich habe eine Matrix mit 50x50 Einträgen (Werte von 0 bis 1).
2D kann ich das ganze wunderbar via plt.matshow() darstellen. Ich habe aber bereits auch schon Realisierungen mit 3D bar plots gesehen.
Vermutlich läuft das ganze über "from mpl_toolkits.mplot3d import Axes3D" ab.

Könnte mir jemand das ganze etwas genauer erklären bitte?
Vielen dank!

Grüße
Benny
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Hier
http://matplotlib.org/examples/mplot3d/hist3d_demo.html
findest Du ein Beispiel zu Axes3D und der Plot-Funktion bar3d.

Die Klasse Axes3D importierst Du nur wegen der Seiteneffekte, damit Du mit
ax = fig.add_subplot(111, projection='3d')
einen 3D-Plot erzeugen kannst.
Wenn Du Axes3D nicht importiert hast, dann bekommst Du mit der Option
projection='3d'
eine Fehlermeldung.
a fool with a tool is still a fool, www.magben.de, YouTube
BennyS
User
Beiträge: 19
Registriert: Montag 28. November 2016, 13:36

Danke schon mal für die schnelle Antwort.
Leider versteh ich das ganze immer noch nicht so ganz.

xpos symbolisiert die X-achse? also in meinem fall[1,2,3,4,5....50]
Das gleiche gilt für ypos.
zpos wäre in meinem fall ja 0...1 da der maximale Wert innerhalb der Matrix 1 ist.
wie weise dem Plot nun meine 50x50 Matrix zu ?

dx,dy,dz gibt die Skalierung an für meinen Plot. Richtig? also in meinem Fall am besten dx,dy=1 und dz=0.1
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Hast Du das Beispiel mal ausprobiert?

Mit ein paar Debugausgaben kannst Du das alles nachschauen.
Das Beispiel zeigt 4 x 4 Balken. Die Arrays xpos, ypos, zpos dx, dy, dz haben alle die Länge 16.

Code: Alles auswählen

print xpos.shape, ypos.shape, zpos.shape # (16,) (16,) (16,)
print dx.shape, dy.shape, dz.shape       # (16,) (16,) (16,)
D.h. jeder Balken hat genau einen Eintrag in jedes dieser 6 Arrays.
xpos, ypos und zpos gibt die Koordinate einer Ecke für jeden Balken an, deshalb sollte zpos in der Regel nur Nuller enthalten. Ausgehend von dieser Ecke geben dx, dy und dz die Ausdehnung jedes Balkens an. In Deinem Fall sollten dx und dy überall den gleichen Wert enthalten, irgendwas zwischen 0.5 und 1.0 und dz enthält die Einträge Deiner Matrix.
a fool with a tool is still a fool, www.magben.de, YouTube
BennyS
User
Beiträge: 19
Registriert: Montag 28. November 2016, 13:36

Ich habe es geschafft :) Danke!

Nur eine Frage hätte ich noch, und zwar :
Wie bekomme ich die Farbskala im 3Dbar plot genauso hin wie im 2D matshow plot? D.h. desto näher an 1, desto mehr geht die Farbe ins rötliche bzw. gegen 0 geht die Farbe ins Dunkelblaue
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

So wird's bunt:

Code: Alles auswählen

from matplotlib import cm
colormap = cm.ScalarMappable()
colormap.set_clim(dz.min(), dz.max())
color = colormap.to_rgba(dz)
ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color=color, zsort='average')
Der Parameter color kann entweder eine einzelne Farbe sein oder ein Array mit einer Farbe pro Balken.
Die Colormap rechnet Zahlenwerte in eine Farbskala um, die Farbskala braucht hierzu den Wertebereich (Zeile 3). Wenn Dir die Standard-Farbskala nicht gefällt, dann such Dir hier eine aus
http://matplotlib.org/examples/color/co ... rence.html
oder definiere Dir selbst eine.
a fool with a tool is still a fool, www.magben.de, YouTube
BennyS
User
Beiträge: 19
Registriert: Montag 28. November 2016, 13:36

Vielen vielen dank! Jetzt ist es so gut wie perfekt. Irgendwie sieht nur die Ansicht noch ein bisschen verbuggt aus.
Ist der Code korrekt?

Code: Alles auswählen

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm


test = np.loadtxt("MAC-0.txt")

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')


dx=50
dy=50
xpos=np.arange(0,dx,1)
ypos=np.arange(0,dy,1)
zpos=np.zeros(dx*dy)
xpos,ypos=np.meshgrid(xpos,ypos)

xpos=xpos.flatten()
ypos=ypos.flatten()
dx=1*np.ones_like(zpos)
dy=dx.copy()
dz=np.loadtxt("0.txt").flatten()


colormap = cm.ScalarMappable()
colormap.set_clim(dz.min(), dz.max())
color = colormap.to_rgba(dz)

ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color=color, zsort='average')

plt.show()
Ich würde gerne ein Bild dafür hochladen aber ich habe dafür irgendwie keinen Knopf gefunden :(
Zuletzt geändert von Anonymous am Dienstag 29. November 2016, 16:46, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@BennyS: `test` wird definiert aber dann gar nicht verwendet.

`dx`, `dy`, `xpos`, und `ypos` werden an verschiedene Dinge gebunden im Laufe des Programms. Beim zweiten Zuweisen an `dx` ist die Multiplikation mit 1 irgendwie überflüssig.

Wahrscheinlich braucht man für `dy` keine Kopie von `dx` sondern könnte einfach den gleichen Wert zuweisen.
Antworten