Grundlagen der NumPy Array-Manipulation

NumPyBeginner
Jetzt üben

Einführung

In diesem Lab werden Sie die grundlegenden Konzepte der NumPy-Array-Manipulation erkunden, wobei der Schwerpunkt speziell auf dem Unterschied zwischen Kopien (copies) und Ansichten (views) liegt. Das Verständnis dieses Unterschieds ist entscheidend für das Schreiben von effizientem und fehlerfreiem numerischem Code in Python. Sie werden Python-Skripte schreiben und ausführen, um diese Konzepte in Aktion zu sehen.

Der Unterschied zwischen einer Kopie und einer Ansicht

In NumPy ist eine Kopie (copy) ein komplett neues Array mit eigenen Daten, während eine Ansicht (view) eine neue Art ist, auf dieselben Daten zuzugreifen. Das Ändern einer Ansicht wirkt sich auf das ursprüngliche Array aus, das Ändern einer Kopie jedoch nicht.

Lassen Sie uns dies in der Praxis sehen. Wir erstellen ein Array, dann eine Ansicht und eine Kopie davon. Anschließend ändern wir beide und beobachten die Auswirkung auf das ursprüngliche Array.

Öffnen Sie zuerst die Datei main.py im Dateiexplorer auf der linken Seite. Ersetzen Sie dann deren Inhalt durch den folgenden Code:

import numpy as np

## --- Teil 1: Ändern einer Ansicht ---
print("--- Modifying a View ---")
## Erstellen eines ursprünglichen Arrays
original_array_view = np.array([1, 2, 3, 4, 5])
print(f"Original array: {original_array_view}")

## Erstellen einer Ansicht des Arrays
view_array = original_array_view.view()
## Ändern des ersten Elements der Ansicht
view_array[0] = 99
print(f"View after modification: {view_array}")
print(f"Original array after modifying the view: {original_array_view}\n")


## --- Teil 2: Ändern einer Kopie ---
print("--- Modifying a Copy ---")
## Erstellen eines weiteren ursprünglichen Arrays
original_array_copy = np.array([10, 20, 30, 40, 50])
print(f"Original array: {original_array_copy}")

## Erstellen einer Kopie des Arrays
copy_array = original_array_copy.copy()
## Ändern des ersten Elements der Kopie
copy_array[0] = 999
print(f"Copy after modification: {copy_array}")
print(f"Original array after modifying the copy: {original_array_copy}")

Speichern Sie nun die Datei und führen Sie sie im Terminal aus, um die Ausgabe zu sehen.

python main.py

Sie sollten die folgende Ausgabe sehen. Beachten Sie, wie sich das ursprüngliche Array geändert hat, als seine Ansicht geändert wurde, aber unverändert blieb, als seine Kopie geändert wurde.

--- Modifying a View ---
Original array: [1 2 3 4 5]
View after modification: [99  2  3  4  5]
Original array after modifying the view: [99  2  3  4  5]

--- Modifying a Copy ---
Original array: [10 20 30 40 50]
Copy after modification: [999  20  30  40  50]
Original array after modifying the copy: [10 20 30 40 50]

Dies verdeutlicht den Kernunterschied: Eine Ansicht ist mit den Originaldaten verknüpft, während eine Kopie vollständig unabhängig ist.

Array Slicing - Erstellen einer Ansicht

Eine sehr gängige Operation in NumPy ist das Slicing (Schneiden), das verwendet wird, um einen Bereich von Elementen aus einem Array auszuwählen. Grundlegendes Slicing erstellt immer eine Ansicht (view) des ursprünglichen Arrays. Dies ist ein wichtiges Merkmal für Speichereffizienz, aber Sie müssen sich bewusst sein, dass die Änderung des Slices die Originaldaten verändert.

Lassen Sie uns dies testen. Löschen Sie den Inhalt von main.py und fügen Sie den folgenden Code hinzu:

import numpy as np

## Erstellen eines Arrays von 0 bis 9
original_array = np.arange(10)
print(f"Original array: {original_array}")

## Erstellen eines Slices des Arrays (Elemente von Index 2 bis 4)
array_slice = original_array[2:5]
print(f"Slice of the array: {array_slice}")

## Ändern des ersten Elements des Slices
print("Modifying the first element of the slice to 100...")
array_slice[0] = 100

## Erneutes Ausgeben des ursprünglichen Arrays, um die Änderung zu sehen
print(f"Original array after modification: {original_array}")

Speichern Sie die Datei und führen Sie sie im Terminal aus.

python main.py

Ihre Ausgabe wird sein:

Original array: [0 1 2 3 4 5 6 7 8 9]
Slice of the array: [2 3 4]
Modifying the first element of the slice to 100...
Original array after modification: [  0   1 100   3   4   5   6   7   8   9]

Wie Sie sehen können, hat die Änderung von array_slice[0] auch original_array[2] geändert. Dies bestätigt, dass der Slice eine Ansicht und keine Kopie war.

Erweitertes Indizieren - Erstellen einer Kopie

Während grundlegendes Slicing Ansichten erstellt, erstellt die fortgeschrittene Indizierung (advanced indexing) immer eine Kopie. Fortgeschrittene Indizierung beinhaltet das Übergeben einer Liste, eines Tupels oder eines anderen Arrays von Indizes zur Auswahl von Elementen. Da die ausgewählten Elemente möglicherweise nicht in einem zusammenhängenden Speicherblock liegen, erstellt NumPy ein neues Array (eine Kopie), um diese zu speichern.

Lassen Sie uns dies mit dem vorherigen Schritt vergleichen. Löschen Sie main.py und fügen Sie diesen Code ein:

import numpy as np

## Erstellen eines Arrays von 0 bis 9
original_array = np.arange(10)
print(f"Original array: {original_array}")

## Verwenden fortgeschrittener Indizierung, um Elemente an den Indizes 1, 3 und 5 auszuwählen
indexed_array = original_array[[1, 3, 5]]
print(f"Indexed array: {indexed_array}")

## Ändern des ersten Elements des neuen Arrays
print("Modifying the first element of the indexed array to 100...")
indexed_array[0] = 100

## Erneutes Ausgeben des ursprünglichen Arrays, um zu sehen, ob es sich geändert hat
print(f"Original array after modification: {original_array}")

Speichern Sie die Datei und führen Sie das Skript aus.

python main.py

Die Ausgabe wird sein:

Original array: [0 1 2 3 4 5 6 7 8 9]
Indexed array: [1 3 5]
Modifying the first element of the indexed array to 100...
Original array after modification: [0 1 2 3 4 5 6 7 8 9]

Dieses Mal bleibt das ursprüngliche Array unverändert. Das indexed_array war eine Kopie, daher hatten Änderungen daran keinen Einfluss auf original_array.

Identifizieren von Kopien und Ansichten mit .base

Manchmal ist nicht offensichtlich, ob eine Operation eine Ansicht oder eine Kopie zurückgegeben hat. NumPy bietet eine zuverlässige Methode zur Überprüfung: das Attribut .base eines Arrays.

  • Wenn ein Array eine Ansicht (view) ist, zeigt sein .base-Attribut auf das ursprüngliche Array-Objekt, zu dem es gehört.
  • Wenn ein Array eine Kopie ist, ist sein .base-Attribut None.

Lassen Sie uns dies verwenden, um unsere Ergebnisse aus den vorherigen Schritten zu bestätigen. Löschen Sie main.py und fügen Sie den folgenden Code hinzu:

import numpy as np

## Erstellen eines ursprünglichen Arrays
original_array = np.arange(10)
print(f"Original array: {original_array}\n")

## Erstellen einer Ansicht mit Slicing
view_slice = original_array[2:5]
print(f"Slice (view): {view_slice}")
## Überprüfen, ob der Slice eine Ansicht des ursprünglichen Arrays ist
print(f"Is the slice a view? {view_slice.base is original_array}\n")

## Erstellen einer Kopie mit fortgeschrittener Indizierung
copy_indexed = original_array[[1, 3, 5]]
print(f"Indexed (copy): {copy_indexed}")
## Überprüfen, ob das indizierte Array eine Kopie ist
print(f"Is the indexed array a copy? {copy_indexed.base is None}")

Speichern Sie die Datei und führen Sie sie vom Terminal aus.

python main.py

Sie erhalten die folgende Ausgabe, die programmatisch bestätigt, dass der Slice eine Ansicht und das indizierte Array eine Kopie ist.

Original array: [0 1 2 3 4 5 6 7 8 9]

Slice (view): [2 3 4]
Is the slice a view? True

Indexed (copy): [1 3 5]
Is the indexed array a copy? True

Das .base-Attribut ist ein unschätzbares Werkzeug zum Debuggen und um sicherzustellen, dass Ihr Code wie erwartet funktioniert.

Zusammenfassung

In diesem Lab haben Sie den entscheidenden Unterschied zwischen einer Kopie und einer Ansicht (view) eines NumPy-Arrays gelernt. Sie haben geübt, beides zu erstellen und beobachtet, wie sich Änderungen auf die Originaldaten auswirken.

  • Sie haben gelernt, dass Methoden wie .view() und grundlegendes Slicing Ansichten erstellen, die speichereffizient sind, aber bei Änderungen zu unbeabsichtigten Nebeneffekten führen können.
  • Sie haben gelernt, dass Methoden wie .copy() und fortgeschrittene Indizierung Kopien erstellen, die unabhängig vom ursprünglichen Array sind.
  • Schließlich haben Sie gelernt, wie Sie das .base-Attribut verwenden, um definitiv zu überprüfen, ob ein Array eine Ansicht oder eine Kopie ist.

Die Beherrschung dieser Konzepte ist ein wichtiger Schritt zum Schreiben robuster und effizienter numerischer Anwendungen mit NumPy.