Introducción a la Indexación en NumPy

NumPyBeginner
Practicar Ahora

Introducción

¡Bienvenido de nuevo! Ahora que entiendes cómo crear arrays de NumPy, es hora de aprender a acceder y manipular los datos dentro de ellos. En este laboratorio, explorarás el indexado (indexing), el método principal para acceder y modificar datos dentro de los arrays de NumPy.

Basándonos en lo que aprendiste

En el laboratorio anterior, aprendiste:

  • Cómo crear arrays utilizando varias funciones de NumPy
  • La diferencia entre arrays y listas de Python
  • Dimensiones de los arrays (1D, 2D, 3D) y tipos de datos

Ahora aprenderás a:

  • Acceder a elementos individuales o grupos de elementos
  • Extraer filas, columnas o regiones específicas de los arrays
  • Utilizar técnicas de selección avanzadas para filtrar datos complejos
  • Modificar datos de arrays a través del indexado

Por qué es importante el indexado

El indexado es fundamental para la manipulación de datos porque te permite:

  • Extraer subconjuntos de datos para análisis
  • Modificar valores específicos en grandes conjuntos de datos
  • Filtrar datos basándose en condiciones
  • Realizar operaciones vectorizadas en elementos seleccionados

Estas habilidades son esenciales para cualquier tarea de análisis de datos o computación científica en Python.

Este es un Guided Lab, que proporciona instrucciones paso a paso para ayudarte a aprender y practicar. Sigue las instrucciones cuidadosamente para completar cada paso y obtener experiencia práctica. Los datos históricos muestran que este es un laboratorio de nivel principiante con una tasa de finalización del 94%. Ha recibido una tasa de reseñas positivas del 100% por parte de los estudiantes.

Indexación y Slicing Básicos en Arrays 1D

Ahora que sabes cómo crear arrays, aprendamos a acceder a su contenido. Todo tu trabajo en este laboratorio se realizará en el archivo indexing_practice.py.

Entendiendo el Indexado de Arrays

Indexado Basado en Cero (Zero-Based Indexing)

Al igual que las listas de Python, los arrays de NumPy utilizan indexado basado en cero. Esto significa que:

  • El primer elemento está en el índice 0
  • El segundo elemento está en el índice 1
  • Y así sucesivamente...

Visualizando los Índices de un Array

Para un array x = [10, 20, 30, 40, 50]:

Índice:  0   1   2   3   4
Valor:  10  20  30  40  50

Por lo tanto, x[0] devuelve 10, x[2] devuelve 30, etc.

Sintaxis de Slicing

El slicing te permite seleccionar un rango de elementos con la sintaxis inicio:fin:paso (start:stop:step):

  • inicio (start): Índice donde comienza el slice (inclusivo)
  • fin (stop): Índice donde termina el slice (exclusivo)
  • paso (step): Cuántos elementos saltar (opcional, por defecto es 1)

Patrones comunes de slicing:

  • x[1:4]: Elementos en los índices 1, 2, 3
  • x[:3]: Los primeros 3 elementos (índices 0, 1, 2)
  • x[2:]: Desde el índice 2 hasta el final
  • x[::2]: Cada dos elementos comenzando desde el índice 0
  • x[::-1]: Invierte el array completo

Primero, abre el archivo indexing_practice.py en el editor. Luego, reemplaza todo su contenido con el siguiente código. Este código crea un array 1D y demuestra cómo acceder a un solo elemento y a un slice de elementos.

import numpy as np

## Create a 1D array with numbers from 0 to 9
x = np.arange(10)
print("Original array:", x)

## Access a single element at index 2
element = x[2]
print("Element at index 2:", element)

## Slice the array from index 1 up to (but not including) index 7, with a step of 2
a_slice = x[1:7:2]
print("Slice from 1 to 7 with step 2:", a_slice)

Después de haber añadido el código a indexing_practice.py, guarda el archivo. Ahora, ejecuta el script desde la terminal ejecutando el siguiente comando:

python indexing_practice.py

Deberías ver la siguiente salida, que muestra el array original, el elemento en el índice especificado y el slice resultante.

Original array: [0 1 2 3 4 5 6 7 8 9]
Element at index 2: 2
Slice from 1 to 7 with step 2: [1 3 5]

Indexación de Arrays Multidimensionales

Ahora trabajemos con arrays que tienen más de una dimensión. ¡Aquí es donde NumPy realmente brilla en comparación con las listas de Python!

Pensando en Múltiples Dimensiones

Arrays 2D como Tablas

Un array 2D es como una hoja de cálculo o una tabla:

  • Las filas son la primera dimensión (horizontal)
  • Las columnas son la segunda dimensión (vertical)
  • Especificas tanto el índice de fila como el de columna: array[fila, columna]

Visualizando el Indexado 2D

Para un array 2D:

array = [[10, 20, 30],
         [40, 50, 60],
         [70, 80, 90]]

Índices:     0,0  0,1  0,2
             1,0  1,1  1,2
             2,0  2,1  2,2
  • array[0, 0] → 10 (primera fila, primera columna)
  • array[1, 2] → 60 (segunda fila, tercera columna)
  • array[2, 1] → 80 (tercera fila, segunda columna)

Selección de Filas o Columnas Completas

  • array[0] o array[0, :] → toda la primera fila [10, 20, 30]
  • array[:, 1] → toda la segunda columna [20, 50, 80]
  • ¡Esto es mucho más conveniente que las listas anidadas de Python!

Practiquemos esto con un array bidimensional (2D). Actualiza tu archivo indexing_practice.py con el siguiente código. Este script crea un array de 3x4 y muestra cómo acceder a un solo elemento y a una fila completa.

import numpy as np

## Create a 2D array (3 rows, 4 columns)
x = np.arange(12).reshape(3, 4)
print("Original 2D array:\n", x)

## Access the element at row 1, column 2
element = x[1, 2]
print("\nElement at (1, 2):", element)

## Access the entire first row (row index 0)
first_row = x[0]
print("\nFirst row:", first_row)

Guarda el archivo y ejecútalo de nuevo desde la terminal:

python indexing_practice.py

La salida mostrará el array 2D y las partes específicas que seleccionaste.

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

Element at (1, 2): 6

First row: [0 1 2 3]

Indexación Avanzada

El slicing básico funciona bien para regiones contiguas, pero a veces necesitas selecciones más complejas. NumPy proporciona dos potentes técnicas de indexado avanzado:

Indexado con Arrays de Enteros (Integer Array Indexing)

Selecciona elementos arbitrarios proporcionando un array de índices. Es como elegir elementos específicos de una lista usando sus posiciones.

Ejemplo del mundo real: Tienes puntuaciones de exámenes y quieres verificar las puntuaciones de los estudiantes en las posiciones 3, 7 y 12:

scores = np.array([85, 92, 78, 95, 88, 76, 91, 89, 84, 93, 87, 90, 82])
student_positions = [3, 7, 12]  ## Estudiantes que te interesan
selected_scores = scores[student_positions]  ## [95, 89, 82]

Indexado con Arrays Booleanos (Boolean Array Indexing / Masking)

Selecciona elementos basándose en condiciones. Crea una "máscara" de valores True/False, luego úsala para filtrar el array.

Ejemplo del mundo real: Filtra las notas aprobatorias (≥ 80) de una clase:

scores = np.array([85, 92, 78, 95, 88, 76, 91, 89, 84, 93])
passing_mask = scores >= 80  ## [True, True, False, True, True, False, True, True, True, True]
passing_scores = scores[passing_mask]  ## [85, 92, 95, 88, 91, 89, 84, 93]

Por Qué Esto es Importante

  • Indexado con enteros: Perfecto para muestrear puntos de datos específicos
  • Indexado booleano: Ideal para filtrar datos y selecciones condicionales
  • Ambos crean copias (no vistas), por lo que las modificaciones no afectan al array original

Probemos ambos. Reemplaza el contenido de indexing_practice.py con el siguiente código:

import numpy as np

## --- Integer Array Indexing ---
x = np.arange(10, 0, -1)
print("Array for integer indexing:", x)

## Select elements at indices 3, 3, 1, and 8
selected_elements = x[np.array([3, 3, 1, 8])]
print("Selected elements with integer array:", selected_elements)


## --- Boolean Array Indexing ---
y = np.array([1., -1., -2., 3.])
print("\nArray for boolean indexing:", y)

## Create a boolean mask for negative elements
mask = y < 0
print("Boolean mask (y < 0):", mask)

## Select elements where the condition is True
negative_elements = y[mask]
print("Elements where y < 0:", negative_elements)

Guarda el archivo y ejecuta el script:

python indexing_practice.py

Tu salida debería demostrar cómo funcionan tanto el indexado con enteros como el booleano para seleccionar datos específicos de tus arrays.

Array for integer indexing: [10  9  8  7  6  5  4  3  2  1]
Selected elements with integer array: [7 7 9 2]

Array for boolean indexing: [ 1. -1. -2.  3.]
Boolean mask (y < 0): [False  True  True False]
Elements where y < 0: [-1. -2.]

Asignación de Valores a Arrays Indexados

El indexado no es solo para leer datos, también es potente para modificar datos. Puedes usar cualquier método de indexado en el lado izquierdo del operador de asignación (=) para cambiar elementos específicos.

Broadcasting: Haciendo Compatibles las Formas (Shapes)

Al asignar valores a arrays indexados, NumPy utiliza broadcasting para hacer que las formas (shapes) sean compatibles. ¡Esta es una de las características más potentes de NumPy!

Reglas de Broadcasting

NumPy puede expandir automáticamente arrays más pequeños para que coincidan con arrays más grandes durante la asignación, siguiendo estas reglas:

  1. Un solo valor a múltiples elementos: Se puede asignar un valor a muchas posiciones
  2. Array pequeño a una selección más grande: Siempre que las dimensiones sean compatibles

Ejemplos de Broadcasting en Asignación

## Un solo valor a un slice
arr = np.array([1, 2, 3, 4, 5])
arr[1:4] = 99  ## [1, 99, 99, 99, 5]

## Array a un slice coincidente
arr = np.array([1, 2, 3, 4, 5])
arr[1:4] = [10, 20, 30]  ## [1, 10, 20, 30, 5]

## Indexado booleano con broadcasting
arr = np.array([1, 2, 3, 4, 5])
arr[arr % 2 == 0] = -1  ## Reemplaza todos los números pares con -1

Notas Importantes

  • El broadcasting solo funciona cuando las formas son compatibles
  • La forma del valor asignado debe poder "encajar" en la selección indexada
  • Esto es mucho más eficiente que iterar manualmente por los elementos

Actualiza tu archivo indexing_practice.py con el siguiente código para ver esto en acción.

import numpy as np

## --- Asignación de un solo valor a un slice ---
x = np.arange(10)
print("Original array:", x)

## Asigna el valor 99 a los elementos del índice 2 al 4
x[2:5] = 99
print("After assigning 99 to slice [2:5]:", x)


## --- Asignación de valores basada en una condición booleana ---
y = np.arange(10)
print("\nOriginal array:", y)

## Asigna el valor -1 a todos los números pares
y[y % 2 == 0] = -1
print("After assigning -1 to even numbers:", y)

Guarda el archivo y ejecútalo desde la terminal:

python indexing_practice.py

La salida mostrará los arrays antes y después de la modificación, demostrando lo potente que es esta característica para la manipulación de datos.

Original array: [0 1 2 3 4 5 6 7 8 9]
After assigning 99 to slice [2:5]: [ 0  1 99 99 99  5  6  7  8  9]

Original array: [0 1 2 3 4 5 6 7 8 9]
After assigning -1 to even numbers: [-1  1 -1  3 -1  5 -1  7 -1  9]

Resumen

En este laboratorio, has aprendido las técnicas esenciales para indexar arrays de NumPy. Comenzaste con el acceso a elementos individuales básicos y el slicing en arrays 1D, similar a las listas de Python. Luego, progresaste al indexado de arrays multidimensionales para seleccionar elementos y sub-arrays específicos. Finalmente, exploraste el indexado avanzado utilizando arrays de enteros y booleanos, y aprendiste a usar estos potentes métodos de selección para modificar datos dentro de un array. Estas habilidades son fundamentales para la manipulación y el análisis de datos efectivos en Python con NumPy.