Rechnen mit Arrays#

Das NumPy Paket stellt eine große Bandbreite diverser Rechenoperationen für Arrays zur Verfügung. Diese lassen sich grob in drei Kategorien unterteilen:

  • Operationen zwischen Arrays gleicher Dimensionen und Skalaren wie das Addieren zweier Arrays oder das Skalieren eines Arrays um einen konstanten Faktor.

  • Anwenden von externen Funktionen auf Arrays, um zum Beispiel den minimalen Eintrag zu bestimmen oder eine Funktion auf jedes Arrayelement anzuwenden.

  • Operationen zwischen Arrays unterschiedlicher Dimension wie beispielsweise Matrix-Vektor-Multiplikation.

Der folgende versteckte Code, der automatisch ausgeführt wird wenn Sie den Live-Code-Modus starten, erzeugt die Vektoren

\( \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \texttt{v} = \begin{pmatrix} -4 \\ 9 \\ 4 \\ 0 \end{pmatrix}, \quad \texttt{v_1} = \begin{pmatrix} 7 \\ 4 \\ 6 \\ 9 \\ 2 \\ 6 \end{pmatrix}, \quad \texttt{v_2} = \begin{pmatrix} 10 \\ 10 \\ 7 \\ 4 \\ 3 \\ 7 \end{pmatrix}. \)

In den kommenden Aufgaben lernen Sie, mithilfe dieser Vektoren die grundlegende Rechenoperationen anzuwenden.

Hide code cell content
import numpy as np

np.random.seed(42)
v = np.random.randint(-10, 10, size = 4)
v1 = np.random.randint(11, size = 6)
v2 = np.random.randint(11, size = 6)

Operationen zwischen Arrays gleicher Dimension und Skalaren#

Ein einfaches Beispiel für die Modifikation eines Arrays besteht darin, zu jedem seiner Elemente einen konstanten (skalaren) Wert zu addieren.

x = np.array([3, 4, 5])
y = x + 5

print(y) 

Aufgabe 1.1

Subtrahieren Sie \(2\) von jedem Element von \(\texttt{v} = \begin{pmatrix} -4 & 9 & 4 & 0 \end{pmatrix}^T\) und speichern Sie das Ergebnis in einer Variable mit dem Namen \(\texttt{w1}\).

# Ihr Code 

Ebenso wie alle Elemente eines Arrays mit einem Skalar addiert oder subtrahiert werden können, können auch alle Elemente mit einem Skalar multiplizieren oder durch einen Skalar dividieren werden.

z = x / 2

print(z)

Aufgabe 1.2

Skalieren Sie jedes Element von \(\texttt{v} = \begin{pmatrix} -4 & 9 & 4 & 0 \end{pmatrix}^T\) mit \(3\) und speichern Sie das Ergebnis in einer Variable mit dem Namen \(\texttt{w2}\).

# Ihr Code 

Genauso wie ein Array und ein Skalar miteinander addiert werden können, können auch zwei Arrays \(\texttt{x}\) und \(\texttt{y}\) derselben Größen addiert werden.

x = np.array([2, 6, 8])
y = np.array([1, 3, 4])

z = x + y

print(z)

Aufgabe 1.3

Erstellen Sie einen Vektor \(\texttt{v_sum}\), der die Summe der Vektoren \(\texttt{v1} = \begin{pmatrix} 7 & 4 & 6 & 9 & 2 & 6 \end{pmatrix}^T\) und \(\texttt{v2} = \begin{pmatrix} 10 & 10 & 7 & 4 & 3 & 7 \end{pmatrix}^T\) ist.

# Ihr Code

Aufgabe 1.4

Erstellen Sie die Variable \(\texttt{v_sum_half}\), die den Vektor \(\texttt{v_sum}\) dividiert durch \(2\) enthält.

# Ihr Code

Der Operator \(\texttt{*}\) führt für zwei Arrays gleicher Größe die elementweise Multiplikation aus, indem er die entsprechenden Elemente eintragsweise miteinander multipliziert.

x = np.array([2, 6, 8])
y = np.array([1, 3, 4])

z = x * y
print(z)

Aufgabe 1.5

Erstellen Sie eine Variable mit dem Namen \(\texttt{w_mult}\), die das elementweise Produkt von \(\texttt{v1} = \begin{pmatrix} 7 & 4 & 6 & 9 & 2 & 6 \end{pmatrix}^T\) und \(\texttt{v1} = \begin{pmatrix} 10 & 10 & 7 & 4 & 3 & 7 \end{pmatrix}^T\) und eine Variable \(\texttt{w_div}\), die den Quotienten von \(\texttt{v1}\) und \(\texttt{v2}\) enthält.

# Ihr Code 

Funktionen auf Arrays anwenden#

Das Paket NumPy stellt grundlegende statistische Funktion zur Verfügung, die Sie auf ein Arrays anwenden können. Zum Beispiel können Sie mit Hilfe der Funktion \(\texttt{np.min()}\) den minimalen Wert eines Vektors \(\texttt{x}\) bestimmen: \(\texttt{x_min = np.min(x)}\).

Aufgabe 2.1

Erstellen Sie die Variable \(\texttt{v_min}\), die den minimalen Wert des Vektors \(\texttt{v_sum} = \begin{pmatrix} 17 & 14 & 13 & 13 & 5 & 13 \end{pmatrix}^T\) enthält.

# Ihr Code 

Das Paket NumPy stellt außerdem Funktionen bereit, die mathematische Operationen für jedes Elements eines Arrays in einem einzigen Befehl ausführen. Beispielsweise können Sie die Quadratwurzel eines jeden Elements im Array \(\texttt{x}\) mit der folgenden Syntax ermitteln: \(\texttt{x_sqrt = np.sqrt(x)}\).

Aufgabe 2.2

Verwenden Sie die Funktion \(\texttt{np.round}\), um eine Variable mit dem Namen \(\texttt{v_round}\) zu erstellen, die die gerundeten Elemente von \(\texttt{v_sum_half} = \begin{pmatrix} 8.5 & 7 & 6.5 & 6.5 & 2.5 & 6.5 \end{pmatrix}^T\) enthält.

# Ihr Code 

Achtung

Handelt es sich um eine Zahl mit Nachkommastelle \(0.5\), dann rundet \(\texttt{np.round}\) auf die nächste gerade Zahl. Das heißt:

  • 1.5 → 2.0

  • 2.5 → 2.0 (weil 2 gerade ist, 3 aber nicht)

  • 3.5 → 4.0

Es folgt eine Übersicht mit einigen geläufigen Funktionen, die auf Vektoren angewendet werden können.

Syntax

Beschreibung

\(\texttt{np.min(x)}\)

Gibt den kleinsten Wert im Array zurück.

\(\texttt{np.max(x)}\)

Gibt den größten Wert im Array zurück.

\(\texttt{np.argmin(x)}\)

Gibt den Index des kleinsten Werts im Array zurück.

\(\texttt{np.argmax(x)}\)

Gibt den Index des größten Werts im Array zurück.

\(\texttt{np.sqrt(x)}\)

Gibt ein Array mit den Quadratwurzeln der Elemente zurück.

\(\texttt{np.abs(x)}\)

Gibt ein Array mit den Absolutbeträgen der Elemente zurück.

\(\texttt{np.round(x)}\)

Rundet jedes Element.

\(\texttt{np.sum(x)}\)

Gibt die Summe aller Elemente zurück.

\(\texttt{np.mean(x)}\)

Gibt den Mittelwert der Elemente zurück.

\(\texttt{np.std(x)}\)

Gibt die Standardabweichung der Werte im Array zurück.

\(\texttt{np.sort(x)}\)

Gibt ein sortiertes Array zurück (aufsteigend).

Operationen zwischen Arrays unterschiedlicher Dimension#

Eine der bekanntesten Rechenoperationen zwischen zwei verschieden dimensionalen Arrays ist die Matrix-Vektor-Multiplikation. NumPy bietet zwei Möglichkeiten diese Auszuführen: die Funktion \(\texttt{np.dot()}\) und den Operator \(@\). Beide liefern jedoch dasselbe Ergebnis.

A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
x = np.array([2, 4, 6])

print(np.dot(A,x))
print(A @ x)

Aufgabe 3.1

Berechnen Sie das Matrix-Vektor-Produkt der Arrays \(\texttt{B}\) und \(\texttt{y}\) und speichern Sie das Ergebnis in einer Variablen \(\texttt{By}\).

B = np.array([[1, 4],[-2, 1],[4, 4],[9, 2]])
y = np.array([2, -1])

# Ihr Code 

Mit der gleichen Syntax kann auch das Produkt \(\texttt{x}^T \cdot \texttt{A}\) berechnet werden.

A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
x = np.array([2, 4, 6])

print(np.dot(x,A))
print(x @ A)

Exkurs: Transponieren eines Arrays#

Ihre innere Mathematikerin wird bei der Matrix-Vektor-Multiplikation vielleicht kurz stutzig geworden sein. Schließlich muss \(\texttt{x}\) ein Spaltenvektor sein damit das Produkt \(\texttt{A} \cdot \texttt{x}\) wohldefiniert ist und ein Zeilenvektor, damit \(\texttt{x} \cdot \texttt{A}\) wohldefiniert ist. Das Ausführen von \(\texttt{A}\ @\ \texttt{x}\) und \(\texttt{x}\ @\ \texttt{A}\) funktioniert für eine quadratische Matrix \(\texttt{A}\) allerdings in beiden Fällen problemlos. An dieser Stelle interpretiert NumPy das Array \(\texttt{x}\) dynamisch entweder als Zeilen- oder Spaltenvektor.

Für \(\texttt{A}\ @\ \texttt{x}\) ist lediglich wichtig, dass die Spaltenanzahl von \(\texttt{A}\) gleich der Länge von \(\texttt{x}\) ist und für \(\texttt{x}\ @\ \texttt{A}\), dass die Zeilennanzahl von \(\texttt{A}\) gleich der Länge von \(\texttt{x}\) ist. Der Ergebnisvektor ist in beiden Fällen wieder ein eindimensionales Array der entsprechenden Länge.

Im Folgenden erklären wir Ihnen, wie Sie ein eindimensionales Array in einen echten Zeilen- oder Spaltenvektor überführt. Dabei wird aus dem eindimensionalen Array ein zweidimensionales, sodass wir tatsächlich von Zeilen und Spalten sprechen können.

Umwandlung in einen Spaltenvektor#

Ein eindimensionales Array \(\texttt{x}\) kann mittels \(\texttt{np.reshape}(\texttt{x}, (-1, 1))\) direkt in einen Spaltenvektor, das heißt ein zweidimensionales Array der Größe \((n, 1)\), überführt werden:

x = np.array([2, 4, 6]) # Vektor der Dimension 1

# Spaltenvektor der Dimension 2 und Größe (3, 1)
spaltenvektor = np.reshape(x, (-1, 1))
print("x = " + str(x))
print("x als Spaltenvektor = \n" + str(spaltenvektor))
print("x als Spaltenvektor Dimension: " + str(spaltenvektor.shape))

Umwandlung in einen Zeilenvektor#

Ebenso kann ein eindimensionales Array \(\texttt{x}\) in einen Zeilenvektor, das heißt ein zweidimnesionales Array der Größe \((1, n)\) überführt werden.

# Zeilenvektor der Dimension 2 und Größe (1, 3)
zeilenvektor = np.reshape(x, (1, -1))
print("x = ", x)
print("x als Zeilenvektor = \n", zeilenvektor)
print("x als Zeilenvektor Dimension: ", zeilenvektor.shape)

Achtung

Beachten Sie, dass Sie nun zwei Indizes brauchen um auf ein Element eines Vektors zuzugreifen, denn \(\texttt{zeilenvektor[0]}\) liefert die erste Zeile des Arrays. Hier also den kompletten Zeilenvektor.

Zeilen- in Spaltenvektoren umwandeln#

Haben Sie bereits einen Zeilenvektor erstellt, können Sie diesen durch Transponieren in einen Spaltenvektor überführen. Dazu stellt NumPy die Funktion \(\texttt{np.transpose}\) bereit, welche dem Transponieren einer Matrix entspricht.

spaltenvektor_transposed = np.transpose(spaltenvektor)
print(spaltenvektor_transposed.shape)

Aufgabe 4.1

Transponieren Sie den Zeilenvektor \(\texttt{zeilenvektor}\) und speichern Sie das Ergebnis in der Variablen \(\texttt{zeilenvektor_transposed}\).

# Ihr Code 

Zusammenfassung#

Ausgangsform

Ziel

Code

eindimensionales Array (n,)

Zeilenvektor (1, n)

\(\texttt{np.reshape(x, (1, -1))}\)

eindimensionales Array (n,)

Spaltenvektor (n, 1)

\(\texttt{np.reshape(x, (-1, 1))}\)

Zeilenvektor (1, n)

Spaltenvektor (n, 1)

\(\texttt{np.transpose(x)}\)

Spaltenvektor (n, 1)

Zeilenvektor (1, n)

\(\texttt{np.transpose(x)}\)

Abschließend schauen wir uns nocheinmal das Beispiel der Matrix-Vektor-Mulitplikation an. Denn diese funktioniert für Zeilen- und Spaltenvektoren nur, wenn die Dimensionen der Vektoren korrekt sind. Außderdem sind die Ergebnisvektoren nun entweder Zeilen- oder Spaltenvektoren.

A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

print(A @ spaltenvektor) # klappt
print(spaltenvektor @ A) # klappt nicht
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

print(zeilenvektor @ A) # klappt
print(A @ zeilenvektor) # klappt nicht

Selbstverständlich können Sie mit den Methoden aus Lektion zur Arrayerstellung auch direkt Zeilen- und Spaltenvektoren erzeugen. Zum Beispiel:

x = np.ones((5, 1)) # Spaltenvektor mit 5 Einträgen
y = np.random.rand(1, 4) # Zeilenvektor mit 4 Einträgen

print("y =", y)
print("x =\n", x)