Fondamentaux de la manipulation des tableaux NumPy

NumPyBeginner
Pratiquer maintenant

Introduction

Dans ce laboratoire, vous explorerez les concepts fondamentaux de la manipulation des tableaux NumPy, en vous concentrant spécifiquement sur la distinction entre les copies et les vues. Comprendre cette différence est crucial pour écrire du code numérique efficace et sans bug en Python. Vous écrirez et exécuterez des scripts Python pour observer ces concepts en action.

Ceci est un Guided Lab, qui fournit des instructions étape par étape pour vous aider à apprendre et à pratiquer. Suivez attentivement les instructions pour compléter chaque étape et acquérir une expérience pratique. Les données historiques montrent que c'est un laboratoire de niveau débutant avec un taux de réussite de 96%. Il a reçu un taux d'avis positifs de 97% de la part des apprenants.

La différence entre une copie et une vue

Dans NumPy, une copie est un tableau entièrement nouveau avec ses propres données, tandis qu'une vue est une nouvelle façon de visualiser les mêmes données. Modifier une vue affectera le tableau d'origine, mais modifier une copie ne le fera pas.

Voyons cela en pratique. Nous allons créer un tableau, puis en faire une vue et une copie. Nous modifierons ensuite les deux et observerons l'effet sur le tableau d'origine.

Tout d'abord, ouvrez le fichier main.py depuis l'explorateur de fichiers à gauche. Ensuite, remplacez son contenu par le code suivant :

import numpy as np

## --- Partie 1 : Modification d'une vue ---
print("--- Modifying a View ---")
## Créer un tableau original
original_array_view = np.array([1, 2, 3, 4, 5])
print(f"Original array: {original_array_view}")

## Créer une vue du tableau
view_array = original_array_view.view()
## Modifier le premier élément de la vue
view_array[0] = 99
print(f"View after modification: {view_array}")
print(f"Original array after modifying the view: {original_array_view}\n")


## --- Partie 2 : Modification d'une copie ---
print("--- Modifying a Copy ---")
## Créer un autre tableau original
original_array_copy = np.array([10, 20, 30, 40, 50])
print(f"Original array: {original_array_copy}")

## Créer une copie du tableau
copy_array = original_array_copy.copy()
## Modifier le premier élément de la copie
copy_array[0] = 999
print(f"Copy after modification: {copy_array}")
print(f"Original array after modifying the copy: {original_array_copy}")

Maintenant, enregistrez le fichier et exécutez-le depuis le terminal pour voir la sortie.

python main.py

Vous devriez voir la sortie suivante. Remarquez comment le tableau d'origine a changé lorsque sa vue a été modifiée, mais est resté inchangé lorsque sa copie a été modifiée.

--- 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]

Cela démontre la différence fondamentale : une vue est liée aux données d'origine, tandis qu'une copie est complètement indépendante.

Découpage d'un tableau - Création d'une vue

Une opération très courante dans NumPy est le découpage (slicing), qui est utilisé pour sélectionner une plage d'éléments d'un tableau. Le découpage de base crée toujours une vue du tableau d'origine. C'est une caractéristique clé pour l'efficacité de la mémoire, mais vous devez être conscient que la modification de la tranche altérera les données d'origine.

Testons cela. Effacez le contenu de main.py et ajoutez le code suivant :

import numpy as np

## Créer un tableau de 0 à 9
original_array = np.arange(10)
print(f"Original array: {original_array}")

## Créer une tranche du tableau (éléments de l'index 2 à 4)
array_slice = original_array[2:5]
print(f"Slice of the array: {array_slice}")

## Modifier le premier élément de la tranche
print("Modifying the first element of the slice to 100...")
array_slice[0] = 100

## Imprimer à nouveau le tableau d'origine pour voir le changement
print(f"Original array after modification: {original_array}")

Enregistrez le fichier et exécutez-le dans le terminal.

python main.py

Votre sortie sera :

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]

Comme vous pouvez le constater, la modification de array_slice[0] a également modifié original_array[2]. Cela confirme que la tranche était une vue, et non une copie.

Indexation avancée - Création d'une copie

Alors que le découpage de base crée des vues, l'indexation avancée crée toujours une copie. L'indexation avancée implique de passer une liste, un tuple ou un autre tableau d'indices pour sélectionner des éléments. Comme les éléments sélectionnés peuvent ne pas être dans un bloc de mémoire contigu, NumPy crée un nouveau tableau (une copie) pour les contenir.

Contrastons cela avec l'étape précédente. Effacez main.py et insérez ce code :

import numpy as np

## Créer un tableau de 0 à 9
original_array = np.arange(10)
print(f"Original array: {original_array}")

## Utiliser l'indexation avancée pour sélectionner les éléments aux indices 1, 3 et 5
indexed_array = original_array[[1, 3, 5]]
print(f"Indexed array: {indexed_array}")

## Modifier le premier élément du nouveau tableau
print("Modifying the first element of the indexed array to 100...")
indexed_array[0] = 100

## Imprimer à nouveau le tableau d'origine pour voir s'il a changé
print(f"Original array after modification: {original_array}")

Enregistrez le fichier et exécutez le script.

python main.py

La sortie sera :

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]

Cette fois, le tableau d'origine reste inchangé. indexed_array était une copie, donc les modifications apportées à celui-ci n'ont pas affecté original_array.

Identification des copies et des vues avec .base

Il n'est pas toujours évident de savoir si une opération a retourné une vue ou une copie. NumPy fournit un moyen fiable de vérifier : l'attribut .base d'un tableau.

  • Si un tableau est une vue, son attribut .base pointera vers l'objet tableau d'origine auquel il appartient.
  • Si un tableau est une copie, son attribut .base sera None.

Utilisons cela pour confirmer nos découvertes des étapes précédentes. Effacez main.py et ajoutez le code suivant :

import numpy as np

## Créer un tableau d'origine
original_array = np.arange(10)
print(f"Original array: {original_array}\n")

## Créer une vue en utilisant le découpage
view_slice = original_array[2:5]
print(f"Slice (view): {view_slice}")
## Vérifier si la tranche est une vue du tableau d'origine
print(f"Is the slice a view? {view_slice.base is original_array}\n")

## Créer une copie en utilisant l'indexation avancée
copy_indexed = original_array[[1, 3, 5]]
print(f"Indexed (copy): {copy_indexed}")
## Vérifier si le tableau indexé est une copie
print(f"Is the indexed array a copy? {copy_indexed.base is None}")

Enregistrez le fichier et exécutez-le depuis le terminal.

python main.py

Vous obtiendrez la sortie suivante, qui confirme par programmation que la tranche est une vue et que le tableau indexé est une copie.

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

L'attribut .base est un outil inestimable pour le débogage et pour s'assurer que votre code se comporte comme prévu.

Résumé

Dans ce laboratoire, vous avez appris la différence cruciale entre une copie et une vue d'un tableau NumPy. Vous avez pratiqué la création des deux et observé comment les modifications affectent les données d'origine.

  • Vous avez appris que des méthodes comme .view() et le découpage de base créent des vues, qui sont économes en mémoire mais peuvent entraîner des effets secondaires involontaires si elles sont modifiées.
  • Vous avez appris que des méthodes comme .copy() et l'indexation avancée créent des copies, qui sont indépendantes du tableau d'origine.
  • Enfin, vous avez appris à utiliser l'attribut .base pour vérifier de manière définitive si un tableau est une vue ou une copie.

Maîtriser ces concepts est une étape clé pour écrire des applications numériques robustes et efficaces avec NumPy.