Matplotlib

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
malikno
User
Beiträge: 26
Registriert: Sonntag 10. April 2011, 21:47

Hallo

schreibe meine dipl auf python und muss jetzt so manche plots erstellen. nun bin ich auf ein problem beim 3d plotten gestossen.

mir ist das normale 3d plotten ja geläufig. man definiere einfach eine funktion mit def test(x,y): ... return f(x,y) und dann erstellt man ein meshgrid, mit zwei vektoren (X,Y). danach kann man einen surface plot erstellen wobei man das meshgrid auf die funktion anwendet. so einfach ist das leider bei mir nicht gegangen.

der funktion "test" werden 2 parameter übergeben, und die zu plottende funktion z = f(x,y) ist auch der return. jedoch muss innerhalb der funktion mal eine if abfrage gemacht werden, wo zum beispiel der übergebene parameter x auf irgendwas geprüft wird.
das ist im wesentlichen der fehler.
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
ich weiss leider nicht genau wie meshgrid arbeitet, und daher bin ich nicht in der lage mein problem zu lösen.
hat jemand eine idee? wär sehr dankbar? im folgenden noch mals das problem mit code dargestellt. hoffe jemand versteht mein problem :)

Code: Alles auswählen

def test(x,y)
    if x > ...:
        ...
    else:
        ...
    return f(x,y)

fig = plt.figure()
ax = fig.gca(projection='3d')

x = np.arange(500, 550, 10)
y = np.arange(400, 450, 10)

X1, Y1 = np.meshgrid(x, y)
  
Z = test(X1,Y1)
surf = ax.plot_surface(X1, Y1, Z, rstride=1, cstride=1, cmap=cm.jet,linewidth=0, antialiased=False)
  
ax.set_zlim3d(1000, 4000)
ax.w_zaxis.set_major_locator(LinearLocator(10))
ax.w_zaxis.set_major_formatter(FormatStrFormatter('%.01f'))
fig.colorbar(surf, shrink=0.5, aspect=1)
plt.show()
wenn meshgrid hier nicht funktioniert, dann wär die alternative jeden wert der funktion selbst zu berechnen und weiters x,y beim surface plot einen z wert zu zuweisen. aber ich weiss leider auch nicht wie das gehen würde.

vielen dank für euro hilfe
Zuletzt geändert von Anonymous am Sonntag 10. April 2011, 22:13, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@malikno: Du denkst wahrscheinlich das `x` ist *ein* skalarer Wert ist. Dem ist aber nicht so -- es ist ein komplettes Numpy-Array. Wenn Du das mit einem skalaren Wert vergleichst, dann bekommst Du als Ergebnis wieder ein Array, bei dem an den einzelnen Positionen `True` oder `False` steht, je nachdem wie was der Vergleich bei dem Element ergibt. Beispiel:

Code: Alles auswählen

In [349]: x = np.array([23, 42, 17, 4])

In [350]: a = x > 25

In [351]: a
Out[351]: array([False,  True, False, False], dtype=bool)

In [352]: if a: pass
   .....: 
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)

/home/bj/<ipython console> in <module>()

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Die Fehlermeldung sagt Dir jetzt, dass ein Array mit mehr als einem Element mehrdeutig sein kann was den Wahrheitsgehalt angeht. Darum kann man ihn nicht bestimmen.

Du müsstest Dich also ein wenig mit Numpy-Arrays und deren Möglichkeiten auseinander setzen. Du könntest es zum Beispiel mit einem Array aus Wahrheitswerten Indexieren -- zum Beispiel dem was Du bei dem Vergleich bekommst. Solche Arrays sind in aller Regel "views" also nur (Teil)Ansichten des ursprünglichen Arrays und Zuweisungen an Werte wirken sich auch auf das Original-Array aus. Beispiel:

Code: Alles auswählen

In [358]: x = np.array([23, 42, 17, 4])

In [359]: x[x > 20]
Out[359]: array([23, 42])

In [360]: x[x > 20] += 10

In [361]: x
Out[361]: array([33, 52, 17,  4])
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

@malikno: Sollte die Fallunterscheidung etwas komplexer werden, könntest du deine Funktion zunächst auch für einen Skalar schreiben und danach mit numpy.vectorize vektorisieren.
malikno
User
Beiträge: 26
Registriert: Sonntag 10. April 2011, 21:47

vielen dank erst mal zu eurer antwort.

ich hatte schon die gleiche vorahnung über den fehler. meshgrid erzeugt ja auch matrizen. nur mir ist nicht bewusst wie meshgrid genau arbeitet. wenn zum beispiel keine if abfrage stattfindet, dann müsste ja trotzdem meshgrid nur einzelne wert übergeben, ansonsten kann ja keine funktion wie zum bsp.:
def test(x,y):
return x+y
für jeden einzelnen x bzw. y wert berechnet werden? oder?
daher kommt ja eigentlich auch mein unverständnis.
wenn ich zum beispiel einen vektor x=np.array([1,2,3]) und y= np.array([1,2,3]) definiere, dann erzeugt mir meshgrid die positionsmatrizen. rechnet mir jedoch die z werte im befehl der funktion test für jeden x bzw. y wert, sprich jede position aus, und gibt mir das zurück.
X1,Y1 = np.meshgrid(x,y)
Z = test(X1,Y1)

Z, wird wie gesagt ja nun für jede position bestimmt. daher dachte ich auch das meshgrid nur immer einzelne positions werte aus den erzeugten meshgrid matrizen an die funktion übergibt. nun funktioniert die oben angeführte funktion. ich habe jedoch wesentlich komplexere funktionen wo eben innerhalb von "test" auch bedingungsabfragen (if) vorkommen.

ich könnte mein problem auch so lösen das ich mir die Z werte selbst in einer matrize zu jeder position errechne. nur wie kann ich dann den surface befehl auf ein tuple von 3 werten anwenden , z. Bsp.
(xi,yi,zi)
...
(10,10,100)
(11,10,101)
...
(10,11,100)
(10,12,101)

das wäre nur ein beispiel, aber ich weiss nicht ob das in dem surface befehl anwendbar ist.

lg
martin
BlackJack

@malikno: Nein es sind eben keine einzelnen Werte die da übergeben werden. Deine `test()`-Funktion funktioniert so, weil die Addition auf Numpy-Arrays so definiert ist, dass Elemente an den gleichen Indizes addiert werden:

Code: Alles auswählen

In [366]: x = np.array([1, 2, 3])

In [367]: y = np.array([4, 5, 6])

In [368]: x + y
Out[368]: array([5, 7, 9])

In [369]: X1, Y1 = np.meshgrid(x, y)

In [370]: X1
Out[370]: 
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

In [371]: Y1
Out[371]: 
array([[4, 4, 4],
       [5, 5, 5],
       [6, 6, 6]])

In [372]: X1 + Y1
Out[372]: 
array([[5, 6, 7],
       [6, 7, 8],
       [7, 8, 9]])
Die `vectorize()`-Funktion löst Dein Problem nicht?
Antworten