For AI agents: use /llms.txt for the Nakafa content index.
Broadcasting ist NumPys Regelsystem zum Verknüpfen von Arrays mit unterschiedlichen, aber kompatiblen Shapes. Dimensionen der Größe eins werden dabei nur gedanklich erweitert, ohne Werte in ein größeres Array zu kopieren. Der NumPy-Leitfaden zum Broadcasting zeigt weitere Beispiele.
Bei der Vektorisierung wirkt ein Ausdruck auf ein ganzes Array. NumPy führt die Schleife im Hintergrund als optimierten, kompilierten Code aus. Das ist oft schneller als eine ausdrücklich geschriebene Python-Schleife.
import numpy as np
# Zwei Arrays erstellen
a = np.array([0, 1, 2])
b = np.array([2, 2, 2])
# Vektorisierungsoperation (elementweise)
result = a + b
print(result)
# Ausgabe: [2 3 4]Im Beispiel addiert NumPy die Elemente an den jeweils entsprechenden Positionen. Wir formulieren die Operation einmal, statt jedes Element in einer Python-Schleife einzeln zu indizieren.
Um zu entscheiden, ob zwei Shapes kompatibel sind, vergleicht NumPy ihre Dimensionen von rechts nach links.
Beim Broadcasting gelten drei Hauptregeln:
ValueError ausimport numpy as np
# 1D-Array mit Skalar
a = np.arange(3) # [0, 1, 2]
b = 5
result = a + b
print(f"Array a: {a}")
print(f"Skalar b: {b}")
print(f"Ergebnis a + b: {result}")
# Erklärung der Formen:
# a hat die Form (3,)
# b hat die Form () - Skalar
# Nach dem Broadcasting wird b zu [5, 5, 5]
# Ausgabe: [5 6 7]Bei Arrays mit unterschiedlicher Dimensionszahl prüft NumPy die Shapes anhand dieser Regeln. So lässt sich beispielsweise dieselbe Operation auf jede Zeile oder jede Spalte einer Matrix anwenden.
import numpy as np
# 2D-Array mit 1D-Array
a = np.ones((3, 3)) # 3x3-Matrix mit Einsen
b = np.arange(3) # [0, 1, 2]
result = a + b
print("Array a (3x3):")
print(a)
print(f"Array b (1D): {b}")
print("Ergebnis a + b:")
print(result)
# Broadcasting findet statt:
# a: Form (3, 3)
# b: Form (3,) -> erweitert zu (1, 3) -> (3, 3)
# b wird zu jeder Zeile von a hinzugefügtimport numpy as np
try:
# Arrays mit inkompatiblen Formen
a = np.arange(6).reshape(2, 3) # Form (2, 3)
b = np.arange(2) # Form (2,)
print(f"Form von Array a: {a.shape}")
print(f"Form von Array b: {b.shape}")
# Dies führt zu einem Fehler
result = a + b
except ValueError as e:
print(f"Error: {e}")
print("Die Array-Formen sind für Broadcasting nicht kompatibel")Arithmetische NumPy-Operatoren arbeiten elementweise, sofern eine Operation nicht ausdrücklich eine andere Bedeutung besitzt, etwa die Matrixmultiplikation.
Wird ein Array mit einem Skalar verknüpft, wendet Broadcasting den Skalar auf jedes Element an. Eine manuelle Indexschleife ist dafür nicht nötig.
import numpy as np
a = np.array([0, 1, 2, 3, 4])
# Addition mit Skalar
print("Addition:")
print(f"a + 1 = {a + 1}")
# Ausgabe: [1 2 3 4 5]
# Multiplikation mit Skalar
print("Multiplikation:")
a *= 2
print(f"a *= 2: {a}")
# Ausgabe: [0 2 4 6 8]
# Potenz
print("Potenz:")
print(f"2**a = {2**a}")
# Ausgabe: [ 1 4 16 64 256]import numpy as np
a = np.array([0, 1, 2, 3, 4])
b = np.array([4, 3, 2, 1, 0])
# Elementweise Subtraktion
print("Subtraktion:")
print(f"a - b = {a - b}")
# Ausgabe: [-4 -2 0 2 4]
# Elementweise Multiplikation
print("Elementweise Multiplikation:")
print(f"a * b = {a * b}")
# Ausgabe: [0 3 4 3 0]
# Matrixmultiplikation (Skalarprodukt)
print("Matrixmultiplikation:")
print(f"a @ b = {a @ b}")
# Ausgabe: 10 (Skalarproduktergebnis)Bei * werden Elemente an entsprechenden Positionen multipliziert. @ führt dagegen eine Matrixmultiplikation nach den Regeln der linearen Algebra aus. np.dot() hat je nach Dimension der Operanden eigene, dokumentierte Regeln und sollte nicht pauschal mit @ gleichgesetzt werden.
Vergleiche erzeugen boolesche Arrays. Sie können anschließend zum Filtern von Daten oder zum Verknüpfen mehrerer Bedingungen verwendet werden.
import numpy as np
a = np.array([0, 1, 2, 3, 4])
b = np.array([0, 0, 2, 4, 4])
# Vergleichsoperationen
print("Größer-als-Vergleich:")
print(f"a > 2: {a > 2}")
# Ausgabe: [False False False True True]
print("Gleichheitsvergleich:")
print(f"a == b: {a == b}")
# Ausgabe: [ True False True False True]
# Logische Operationen
print("Logische ODER-Verknüpfung:")
print(f"(a > 2) | (a == b): {(a > 2) | (a == b)}")
# Ausgabe: [ True False True True True]Für elementweise boolesche Logik verwendest du ~ für NOT, & für AND und | für OR oder die entsprechenden np.logical_*-Funktionen. Setze jeden Vergleich in Klammern, weil die Operatoren eine andere Priorität als Vergleiche haben. Die skalaren Python-Operatoren not, and und or führen keine elementweise Array-Logik aus.
Reduktionsfunktionen fassen viele Elemente zu weniger Werten zusammen. Ohne Angabe einer Achse können sie das gesamte Array auf einen Wert reduzieren. Mit einer Achse reduzieren sie nur diese Dimension. Bei einer Tabelle mit Prüfungsergebnissen kann so etwa ein Mittelwert pro Fach oder pro Person entstehen.
NumPy stellt dafür statistische Funktionen bereit, die entweder auf dem gesamten Array oder entlang ausgewählter Achsen arbeiten.
import numpy as np
# 2D-Beispielarray erstellen
data = np.array([[3, 0, -1, 1],
[2, -1, -2, 4],
[1, 7, 0, 4]])
print("Data array:")
print(data)
# Statistiken zum gesamten Array
print(f"Gesamtsumme: {np.sum(data)}")
print(f"Mittelwert: {np.mean(data):.2f}")
print(f"Kleinster Wert: {np.min(data)}")
print(f"Maximalwert: {np.max(data)}")
print(f"Standardabweichung: {np.std(data):.2f}")
# Ausgabe:
# Gesamtsumme: 18
# Mittelwert: 1.50
# Kleinster Wert: -2
# Maximalwert: 7
# Standardabweichung: 2.50Bei einem zweidimensionalen Array reduziert axis=0 die Zeilendimension und liefert einen Wert pro Spalte. axis=1 reduziert die Spaltendimension und liefert einen Wert pro Zeile.
Wenn Sie Achsen verstehen, können Sie steuern, wie statistische Funktionen auf mehrdimensionale Daten wirken. Wenn Sie beispielsweise monatliche Verkaufsdaten für verschiedene Produkte haben, können Sie den Gesamtumsatz pro Produkt oder pro Monat berechnen.
import numpy as np
data = np.array([[3, 0, -1, 1],
[2, -1, -2, 4],
[1, 7, 0, 4]])
# Operationen entlang der Achse=0 (für jede Spalte)
print("Maximum jeder Spalte (Achse=0):")
print(f"max(axis=0): {np.max(data, axis=0)}")
# Ausgabe: [3 7 0 4]
print("Index des Maximums in jeder Spalte:")
print(f"argmax(axis=0): {np.argmax(data, axis=0)}")
# Ausgabe: [0 2 2 1]
# Operationen entlang der Achse=1 (für jede Zeile)
print("Maximum jeder Zeile (Achse=1):")
print(f"max(axis=1): {np.max(data, axis=1)}")
# Ausgabe: [3 4 7]
print("Index des Maximums in jeder Zeile:")
print(f"argmax(axis=1): {np.argmax(data, axis=1)}")
# Ausgabe: [0 3 1]Shape-Operationen verändern, wie dieselben Elemente indiziert werden. Ein Reshape behält die Anzahl der Elemente bei, ordnet sie aber anderen Dimensionen zu.
Neu erzeugte NumPy-Arrays sind häufig C-kontiguierlich. Dann ändert sich der letzte Index im Speicher am schnellsten. Views aus Slices oder Transpositionen können jedoch andere Strides besitzen, sodass Arrays nicht immer in einem einzigen einfachen Zeilenlayout gespeichert sind. Beim Reshape oder Flatten spielen deshalb die Regeln für order und Strides eine Rolle.
import numpy as np
# 2D-Array erstellen
a = np.array([[0, 1], [2, 3]])
print("2D-Array:")
print(a)
print(f"Form: {a.shape}")
# Sehen Sie, wie es im Speicher gespeichert wird
print(f"Im Speicher gespeichert als: {a.ravel()}")
# Ausgabe: [0 1 2 3] (row-major order)flatten() und ravel() liefern beide ein eindimensionales Array. flatten() erzeugt immer eine Kopie. ravel() liefert wenn möglich eine View und erstellt eine Kopie, wenn das Speicherlayout es erfordert.
import numpy as np
# Diagonales Array erstellen
a = np.diag([1, 2, 3])
print("Diagonales Array:")
print(a)
# flatten - erstellt eine unabhängige Kopie
b_flatten = a.flatten()
print(f"Ergebnis von flatten: {b_flatten}")
# Das Ändern der Flatten-Werte hat keinen Einfluss auf das ursprüngliche Array
b_flatten[0] = 9
print(f"Nach Änderung der flatten-Kopie: {b_flatten}")
print("Das ursprüngliche Array bleibt gleich:")
print(a)
print()
# ravel - versucht eine View zu erstellen und ist dadurch effizienter
b_ravel = a.ravel()
print(f"Ravel-Ergebnis: {b_ravel}")
# Das Ändern der Ravel-Werte wirkt sich auf das ursprüngliche Array aus
b_ravel[0] = 9
print(f"Nach Änderung der ravel-Ansicht: {b_ravel}")
print("Ursprüngliches Array geändert:")
print(a)reshape() ändert den Shape, solange die Anzahl der Elemente gleich bleibt, und liefert wenn möglich eine View. Die unten verwendete Methode ndarray.resize() verändert dagegen das ursprüngliche Array direkt.
import numpy as np
# Diagonales Array erstellen und mit flatten abflachen
a = np.diag([1, 2, 3])
a_flat = a.flatten()
print(f"Flaches Array: {a_flat}")
# reshape - ändert die Form bei gleicher Elementanzahl
b = a_flat.reshape(3, 3)
print("Ergebnis von reshape(3, 3):")
print(b)
# Werte in der reshape-Ansicht ändern
b[0, 0] = 9
print("Nach Wertänderung:")
print(b)
print(f"Ursprüngliches flaches Array: {a_flat}") # Ändert sich, weil reshape eine Ansicht erstellt
# resize - ändert die Form direkt und gibt keinen Wert zurück
a_flat.resize(3, 3)
print("Nach der Größenänderung:")
print(a_flat) # Jetzt ist a_flat 2DEine Transposition vertauscht die Reihenfolge der Array-Achsen. Bei einem zweidimensionalen Array werden Zeilen und Spalten getauscht. NumPy bietet dafür die Methode transpose() und das kürzere Attribut .T.
import numpy as np
# 2x4-Array erstellen
a = np.linspace(1, 8, 8).reshape(2, 4)
print("Ursprüngliches Array (2x4):")
print(a)
# Mit Methode transponieren
b = a.transpose()
print("Transponierungsergebnis (4x2):")
print(b)
# Mit .T-Attribut transponieren (kürzer)
c = a.T
print("Verwendung von .T:")
print(c)
# Prüfen, ob die Transponierung eine Ansicht ist
print("Ist die Transponierung eine Ansicht?", np.shares_memory(a, b))Die Z-Standardisierung zentriert jedes Merkmal auf den Mittelwert und skaliert es auf die Standardabweichung . Sie ist nur für Merkmale mit einer von null verschiedenen Standardabweichung definiert und bringt Merkmale auf vergleichbare numerische Skalen.
Die Formel lautet . Dabei gilt:
import numpy as np
# Beispieldaten erstellen: fünf Beobachtungen mit je drei Merkmalen
np.random.seed(42)
X = np.random.randn(5, 3) * 10 + 50 # Daten mit Mittelwert~50, std~10
print("Originaldaten:")
print(X)
print(f"Datenform: {X.shape}")
# Mittelwert und Standardabweichung für jede Spalte berechnen
mu = np.mean(X, axis=0) # Mittelwert jeder Spalte
sigma = np.std(X, axis=0) # Standardabweichung jeder Spalte
print(f"Mittelwert jedes Merkmals: {mu}")
print(f"Standardabweichung jedes Merkmals: {sigma}")
# Z-Transformation durchführen
Z = (X - mu) / sigma
print("Daten nach Z-Transformation:")
print(Z)
# Ergebnis der Standardisierung prüfen
print("Überprüfung der Standardisierung:")
print(f"Neuer Mittelwert: {np.mean(Z, axis=0)}") # Sollte in der Nähe von 0 liegen
print(f"Neue Standardabweichung: {np.std(Z, axis=0)}") # Sollte in der Nähe von 1 liegen
# Neue Mittelwerte: [ 1.24344979e-15 8.88178420e-17 -1.77635684e-16] (nahe 0)
# Neue Standardabweichungen: [1. 1. 1.]Die Standardisierung verhindert, dass allein unterschiedliche Einheiten große Skalenunterschiede verursachen. Sie garantiert weder gleiche Bedeutung noch gleichen Einfluss, denn beides hängt weiterhin vom Modell und von den Daten ab. Körpergröße in Zentimetern und Gewicht in Kilogramm werden nach der Standardisierung beispielsweise numerisch vergleichbar.
Weitere Erklärungen und Beispiele findest du in der offiziellen NumPy-Dokumentation.