mplotlib 3D surface plot erstellen

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
thedome
User
Beiträge: 8
Registriert: Mittwoch 25. Februar 2015, 12:06

hallo, ich habe erst vor einigen tagen mit python angefangen und sitze seit einiger zeit an einem code, um mehrere datensätze einzulesen und als 3d surface auszugeben. es handelt sich bei den datensätzen um spalten einer tabelle, die in eine liste eingetragen werden. da mehrere dateien eingelesen werden, werden diese listen nochmals in eine liste eingetragen, welche ich anschließend als 3d surface ausgeben möchte. es werden also zwei spalten aus mehreren dateien ausgelesen, welche dann jeweils die x und y koordinaten darstellen. die z koordinate ist dann der dateiname, wobei dieser durch eine aufsteigende zahl ersetzt wird. das problem ist (womöglich), dass die anzahl der werte in den spalten für jede datei unterschiedlich sind. das heißt, dass ich bspw. für "z=1" 20 werte für x und y habe, aber bei "z=2" nur 10 x und y werte.
ich habe zwei fragen:
1. ist es überhaupt möglich, aus solchen daten eine oberfläche zu generieren?
2. ich erhalte für den unten stehenden code folgende fehlermeldung:
File "C:\Python34\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py", line 1620, in plot_surface
avgzsum = sum(p[2] for p in ps2)
TypeError: unsupported operand type(s) for +: 'int' and 'list'

Ich habe mir die axes3d.py angeguckt, aber werde da leider nicht draus schlau.

Code: Alles auswählen

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np
from os import path, chdir, listdir
import glob

mypath = path.join('c:','\\','path')
chdir (mypath)
Typ='*.dat'
Dateiinhalt=glob.glob(Typ)

Frliste=[]
Reliste=[]
Run=[]
Runliste=[]

for i in range(len(Dateiinhalt)):

    Mo, Re, Fr = np.loadtxt(Dateiinhalt[i],skiprows=1,unpack=True)
    Frliste.append(list(Fr))
    Reliste.append(list(Re))
    Run=[]
    j=0
    for j in range(len(Fr)):       #dies dient dazu, ein array für die z koordinaten zu erstellen
        Run.append(i+1)
    Runliste.append(list(Run))


fig = plt.figure()
ax = fig.gca(projection='3d')
X = Frliste
Y = Reliste
Z = Runliste
X, Y = np.meshgrid(X, Y)

surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
        linewidth=0, antialiased=False)

ax.set_zlim(0, 40)

ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()

Danke schonmal für jede Hilfe!
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Probier mal (Zeile 35):

Code: Alles auswählen

Z = np.array(Runliste)
und prüfe nach Zeile 36 ob X.shape, Y.shape und Z.shape übereinstimmen:

Code: Alles auswählen

print( X.shape )
print( Y.shape )
print( Z.shape )
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

thedome hat geschrieben:das problem ist (womöglich), dass die anzahl der werte in den spalten für jede datei unterschiedlich sind.
Genau das ist das Problem. Z muss in jeder Zeile gleichviel Spalten haben.

Füll die fehlenden Spaltenwerte mit np.NaN auf.
a fool with a tool is still a fool, www.magben.de, YouTube
thedome
User
Beiträge: 8
Registriert: Mittwoch 25. Februar 2015, 12:06

MagBen hat geschrieben:Probier mal (Zeile 35):

Code: Alles auswählen

Z = np.array(Runliste)
und prüfe nach Zeile 36 ob X.shape, Y.shape und Z.shape übereinstimmen:

Code: Alles auswählen

print( X.shape )
print( Y.shape )
print( Z.shape )
vielen Dank MagBen, Z = np.array(Runliste) habe ich schon probiert, da hat sich nichts geändert.
Folgendes kam bei X, Y, Z shape raus:

(1, 36) -> X
(36, 1) -> Y
(36,) ->Z

und wieder die Fehlermeldung:: File "C:\Python34\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py", line 1620, in plot_surface
avgzsum = sum(p[2] for p in ps2)
TypeError: unsupported operand type(s) for +: 'int' and 'list'
MagBen hat geschrieben:
thedome hat geschrieben:das problem ist (womöglich), dass die anzahl der werte in den spalten für jede datei unterschiedlich sind.
Genau das ist das Problem. Z muss in jeder Zeile gleichviel Spalten haben.

Füll die fehlenden Spaltenwerte mit np.NaN auf.
Ich habe in den Zeilen 35 und 36 folgendes ergänzt

Code: Alles auswählen

Z = np.array(Runliste)
np.nan_to_num(Z)
erhalte dann aber folgende Fehlermeldung:
File "C:\Python34\lib\site-packages\numpy\lib\ufunclike.py", line 113, in isposinf
nx.logical_and(nx.isinf(x), ~nx.signbit(x), y)
TypeError: ufunc 'isinf' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
:K
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

thedome hat geschrieben:Folgendes kam bei X, Y, Z shape raus:
(1, 36) -> X
(36, 1) -> Y
(36,) ->Z
Bei allen drei muss das Gleiche rauskommen.

X und Y müssen vor
X, Y = np.meshgrid(X, Y)
1D Arrays bzw. Listen sein, also nicht Listen von Listen, genau das machst Du aber in den Zeilen 22 und 23. Lass das list mal weg;

Code: Alles auswählen

    Frliste.append(Fr)
    Reliste.append(Re)
thedome hat geschrieben:Ich habe in den Zeilen 35 und 36 folgendes ergänzt
Das reicht nicht. Du musst vor Zeile 28 die Liste Run mit NaN auffüllen, sodass die Liste Run immer die selbe Länge hat. NaN kann man in Matplotlib wunderbar nutzen um Lücken in Kurven oder Löcher in Flächen zu definieren. Probier mal diesen Code aus:

Code: Alles auswählen

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

nx = 100
ny = 30
x = np.linspace(-1,1,nx)
y = np.linspace(-1,1,ny)

x_2d, y_2d = np.meshgrid(x, y)
z_2d = np.cos(np.pi * x_2d) * np.cos(np.pi * y_2d)

print(x_2d.shape) # (30, 100)
print(y_2d.shape) # (30, 100)
print(z_2d.shape) # (30, 100)

fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(x_2d, y_2d, z_2d, rstride=1, cstride=1, cmap=cm.coolwarm,)

# Jetzt brennen wir ein Loch rein
z_2d[np.sqrt(x_2d**2 + y_2d**2)<.7 ] = np.NaN

fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(x_2d, y_2d, z_2d, rstride=1, cstride=1, cmap=cm.coolwarm,)

plt.show()
a fool with a tool is still a fool, www.magben.de, YouTube
Antworten