# --- # jupyter: # jupytext: # text_representation: # extension: .py # format_name: percent # format_version: '1.3' # jupytext_version: 1.14.0 # kernelspec: # display_name: Python [conda env:CompWS22] * # language: python # name: conda-env-CompWS22-py # --- # %% [markdown] # # Einführung in NumPy # NumPy ist ein Paket das mathematische Funktionen, einen Zufallszahlengenerator, grundlegende Verfahren der linearen Algebra und vieles mehr zur Verfügung stellt. # %% import numpy as np # %% np.array((1, 2)) # %% np.pi # %% np.sin(np.pi) # %% np.exp(1) # %% [markdown] # Wir werden uns anschauen, wie man unter Nutzung von NumPy Vektoren und Matrizen definiert und einfache Operationen durchführt. # %% [markdown] # ## Einfache Vektoren und Matrizen in NumPy erzeugen # %% u = np.array([1, 2, 3]) # 1D Array (Vektor) # %% v = np.array([4, 5]) # %% A = np.array([[1, 2, 3], [3, 4, 5], [5, 6, 7]]) # 2D Array (Matrix) # %% print(type(u), type(v)) # %% print(type(A)) # %% w = np.array(5) # eine skalare Größe (0D array) # %% print(type(w)) # %% 3*u # jedes Element wird mit 3 multipliziert # %% e = np.array([1, 1, 1]) e # %% u - 3*e # mit 1D arrays kann wie mit Vektoren rechnen # %% [markdown] # ## Attribute eines NumPy Arrays # %% [markdown] # Anzahl der Dimensionen eines NumPy arrays anzeigen: # %% u.ndim # ndim ist ein Attribut # %% w.ndim # %% A.ndim # %% [markdown] # Es gibt __ndim__ auch als Methode (Funktion): # %% np.ndim(u) # %% np.ndim(A) # %% [markdown] # Die Elemente des __shape__ Tupel geben die Länge der entsprechenden Array Dimension an. # # Ebenso wie ndim gibt es auch shape sowohl als Attribut als auch als Methode. # %% A.shape # %% u.shape # %% w.shape # %% np.shape(A) # %% [markdown] # __size__ gibt die Anzahl der Elemente des Arrays an: # %% u.size, A.size, w.size # %% np.size(A) # auch size gibt es als Methode # %% [markdown] # ## vstack und hstack # Füge eine Zeile oder Spalte e zur 3x3 Matrix A hinzu # %% # Zeile anhängen mit np.vstack np.vstack((A, e)) # %% np.hstack((A, e)) # %% e.shape=(3, 1) np.hstack((A, e)) # %% np.hstack((A, A)) # %% [markdown] # Alternativ kann man auch die (mächtigere) Funktion # "np.concatenate" verwenden (siehe Hilfe). # %% [markdown] # ## Zugriff auf Einträge und Änderung von Einträgen # %% C = np.vstack((A, 2*A)) C # %% C[0, 0] # %% C[-1, -2] # %% C[-1, -1] = 101 C # %% C[2, :] # %% C[2, :] = -1 C # %% C[1::2, 1] # %% C[2:4, 1:3], C[2:4, 0:-1] # %% [markdown] # ## Einfache Methoden für NumPy Arrays # %% u # %% a = np.array([4,6,7]) # %% [markdown] # *, / , % und ** wirken eintragsweise, wie + und - # %% u*a # %% A/A # %% u**u # %% A.T # transponierte Matrix # %% A.trace() # Spur # %% [markdown] # ### @ Operator # eine allgmeine Matrixmultplikation # # Skalarprodukt von Vektoren # %% u@u # %% np.dot(u,u) # %% [markdown] # Auch die Matrix-Vektor Multiplikation und die Matrix-Matrix Multiplikation wird durch @ oder np.dot() berechnet. # # u ist weder ein Zeilen- noch ein Spaltenvektor, sondern ein flacher (flat) Vektor. # %% A@u # %% u@A # %% A@A # %% np.dot(A, A) # %% [markdown] # ### reshape # mit reshape oder np.newaxis kann man aus einem flachen Vektor eine Zeilen- oder Spaltenvektor machen # %% u_spalte = u.reshape(-1, 1) # Spaltenvektor u_spalte # %% u_s_ = u[:, np.newaxis] u_s_ # %% u[0] = 1 u_spalte, u_s_ # u_spalte und u_s_ sind nur Ansichten von u und zeigen auf dieselben Einträge im Speicher # %% a = a.reshape(1, -1) a # %% u_zeile = u[np.newaxis, :] u_zeile # %% u_spalte@u_zeile , u_zeile@u_spalte # Skalarprodukt und äußeres Produkt # %% u_spalte@A # %% [markdown] # ### Weitere Arrayoperationen # %% [markdown] # np.max(A) oder A.max() liefert das maximale Matrixelement: # %% np.max(A), A.max() # %% [markdown] # Maximum entlang der ersten Achse # %% A # %% A.max(1) # %% [markdown] # Maximum der 1. Zeile # %% np.max(A[0, :]) # %% [markdown] # "flatten" A in ein 1-dim. Array # %% A.flatten() # %% [markdown] # np.argmin(A) / np.argmax(A) liefert Index bezüglich "flattened array" des kleinsten / größten Matrixelements # Falls das größte / kleinste Element mehrfach vorkommt, dann erhält man den ersten Index # %% A.argmax(), A.flatten()[np.argmax(A)] # %% B = np.array([3*i-4 for i in range(9)]).reshape(3, 3) B # %% np.maximum(A, B) # elementweises maximum (analog np.minimum) # %% [markdown] # ### Kronecker Produkt # Erzeugt ein zusammengesetztes Array aus Blöcken des 2. Arrays # unter Verwendung der durch das 1. Array beschriebenen Skalierung # %% # einmal so rum np.kron([1, 10, 100], [5, 6, 7]) # anders rum kommt was anderes raus np.kron([5, 6, 7], [1, 10, 100]) # %% I2 = np.array([[1, 0], [0, 2]]) E2 = np.array([[1, 1], [2, 2]]) np.kron(I2, E2) np.kron(E2, I2) # %% [markdown] # ## Definition spezieller Matrizen # %% E = np.ones((3, 3)) # Matrix aus Einsen Z = np.zeros((3, 3)) # Nullmatrix I = np.eye(3) # Identität A = np.arange(3) # %% E, Z, I, A # %% np.eye(4, 6, k=1) # erste obere Nebendiagonale # %% np.eye(4, 6, k=-1) # erste untere Nebendiagonale # %% np.eye(4, 6) # Default Wert ist k=0, Hauptdiagonale # %% A = np.arange(16).reshape(4, 4) A # %% # Diagonale von A # %% np.diag(A) # %% # Untere Dreiecksmatrix np.tril(A) # %% # Obere Dreiecksmatrix np.triu(A) # %% # np.diag kann auch Diagonalmatrizen erzeugen B = np.diag(v.flatten()) B # %% # np.diag für Nebendiagonalen NU = np.diag(A, k=1) # obere Nebendiagonale NU # %% NL = np.diag(A, k=-1) # untere Nebendiagonale NL # %% # Benutze np.diag zur Definition von Matrizen x = [1, 2, 3] A = np.diag(x, k=-1) + np.diag(x, k=1) A # %% [markdown] # ## Broadcasting # +, -, * , %, / ** wirken eintragsweise wobei die fehlende Dimension expandiert wird. # %% A = np.array([[1, 2], [3, 4]]) v = np.array([-5, 7]) display(A, v) # %% # Das erste Element von v wird zu jeder zu jedem Element der ersten Spalte addiert A+v # %% #' Das erste Element von v wird ... A*v # %% A**v.astype('float') # %% # zu jedem Eintrag wird 1 addiert A + 1 # %% # jeder Eintrag wird durch 3 dividiert A / 3 # %% # 3 wird durch jeden Eintrag dividiert 3 / A # %% [markdown] # __Broadcastingregel__ # (aus https://numpy.org/doc/stable/user/basics.broadcasting.html) # # When operating on two arrays, NumPy compares their shapes element-wise. It starts with the trailing (i.e. rightmost) dimensions and works its way left. Two dimensions are compatible when # # 1. they are equal, or # # 2. one of them is 1 # # If these conditions are not met, a ValueError: operands could not be broadcast together exception is thrown, indicating that the arrays have incompatible shapes. The size of the resulting array is the size that is not 1 along each axis of the inputs. # # Arrays do not need to have the same number of dimensions. # %% DreiArray = np.array(np.arange(3*4*5)).reshape(3, 4, 5) DreiArray.shape # %% ZweiArray = np.array(np.arange(3*4)).reshape(3, 4) # %% DreiArray + ZweiArray # %% DreiArray_neu = np.array(np.arange(3*4*5)).reshape(5, 3, 4) DreiArray_neu.shape # %% EinsArray = np.array(np.arange(5)).reshape(5, 1, 1) # %% #DreiArray_neu + ZweiArray + EinsArray # %% [markdown] # ## Beispiel zur Verwendung von Index-Arrays. # Erzeuge einen Vektor, der die Gegendiagonale einer Matrix enthält # %% A = np.arange(16).reshape(4, 4) A # %% i = np.arange(4) j = i[::-1] j, i # %% b = A[i, j] b # %% [markdown] # ## Verwende boolsche Ausdrücke bei der Definition von Matrizen # %% # Bsp: Setze alle negativen Matrixeinträge auf Null A B = A - 2*A.T B # %% B[B < 0] = 0 B # %% # elementweises logisches "oder" und "und" B = A - A.T B # %% # Welche Elemente von B sind kleiner als -5 ODER größer als 6? index_array = np.logical_or(B < -5, B > 6) index_array # %% # Welche Elemente von B sind kleiner als 2 UND größer als 0? np.logical_and(B < 7, B > 0) # %% B[index_array] = 100 B # %% [markdown] # ## Achtung # %% a = np.array([1, -2.25]) # %% a.dtype # %% a[0] = 1.+1j # %% ac = np.array([1, -2.25], dtype='complex') ac.dtype # %% ac[0] = 10.+10j # %% a + ac # %% np.sqrt(a) # %% np.sqrt(ac) # %% [markdown] # Die NumPy-Funktionen in emath (power, exp, log, und inverse trigonometrische Funktionen) passen den Ausgabedatentyp an, wenn der Ausgabedatentyp vom Eingabedatentyp abweicht. # %% np.emath.sqrt(a) # %% np.info(np.emath) # %%