Arrays de NumPy
Los objetos ndarray de NumPy almacenan datos numéricos homogéneos y exponen operaciones vectorizadas que reemplazan los lentos bucles de Python.
Receta
Tarjeta de referencia rápida - lista para copiar y pegar.
import numpy as np
# Crear, convertir dtype, vectorizar
a = np.array([1, 2, 3], dtype=np.float64)
b = np.arange(3) # [0, 1, 2]
result = a * 2 + b # broadcasting + ufunc
print(result.shape, result.dtype)Cuándo usar esto:
- Transformaciones numéricas en millones de valores (matemáticas, máscaras, agregaciones)
- Álgebra lineal, estadísticas y preprocesamiento de imágenes/tensores
- Interoperabilidad con pandas, SciPy y bibliotecas de ML que esperan entrada ndarray
- Cualquier bucle intensivo que, según el profiling, pase tiempo en el bytecode de Python
Ejemplo de Trabajo
import numpy as np
# Matriz de ingresos mensuales: filas = regiones, columnas = meses
revenue = np.array(
[[120_000, 135_000, 128_000],
[98_000, 102_000, 110_000],
[150_000, 148_000, 155_000]],
dtype=np.int64,
)
# Tasa de crecimiento por región frente al mes anterior (la columna 0 no tiene anterior)
growth = np.diff(revenue, axis=1) / revenue[:, :-1]
# Normalizar cada región a su propia media (broadcasting)
normalized = (revenue - revenue.mean(axis=1, keepdims=True)) / revenue.std(axis=1, keepdims=True)
# Enmascarar celdas de bajo rendimiento
threshold = revenue.mean()
under = np.where(revenue < threshold, revenue, 0)
print("forma de growth:", growth.shape)
print("media normalizada por fila:", normalized.mean(axis=1))
print("total de bajo rendimiento:", under.sum())Lo que esto demuestra:
- Creación 2-D con
dtypeexplícito para matemáticas enteras estables np.diffa lo largo deaxis=1para el cambio mes a mes columna a columna- Broadcasting con
keepdims=Truepara que las estadísticas de fila se alineen con la forma de la matriz np.wherecomo una condición vectorizada sinifde Python por celda
Inmersión Profunda
Cómo Funciona
- Un
ndarrayes un buffer contiguo más metadatos de forma/pasos - todos los elementos comparten un único dtype. - Las funciones universales (ufuncs) aplican operaciones elemento a elemento en bucles compilados, a menudo liberando el GIL.
- El broadcasting compara formas desde la derecha: las dimensiones coinciden cuando son iguales o uno de los lados es 1.
- Las vistas comparten memoria con el array padre; las copias son explícitas (
arr.copy()) o provienen de asignaciones incompatibles.
Patrones de Creación
| Función | Uso Típico |
|---|---|
np.array | A partir de secuencias de Python |
np.arange / np.linspace | Rangos espaciados uniformemente |
np.zeros / np.ones / np.full | Buffers preasignados |
np.random.default_rng | Datos aleatorios reproducibles |
Referencia Rápida de dtype
| dtype | Cuándo |
|---|---|
int32 / int64 | Conteos e IDs |
float32 | Características grandes de ML donde el compromiso de precisión está bien |
float64 | Precisión analítica predeterminada |
bool | Máscaras y predicados |
Notas de Python
import numpy as np
# Prefiere dtype explícito al ingerir
ids = np.array(["1", "2", "3"], dtype=np.int64) # ValueError - convierte cadenas primero
# Usa default_rng, no el legado np.random.seed
rng = np.random.default_rng(42)
samples = rng.normal(0, 1, size=10_000)
# np.ndarray no es un reemplazo directo para list - .append no existeTrampas
- Tipos mixtos en
np.array-np.array([1, 2.5, 3])se convierte en float64 y puede sorprender al código entero posterior. Solución: convierte explícitamente en la creación. - División entera -
/siempre promueve a flotante;//trunca hacia infinito negativo. Solución: usanp.floor_dividecuando necesites un truncamiento consistente. - Copias silenciosas vs vistas - el indexado "fancy" (
arr[[0, 2]]) devuelve una copia; los "slices" a menudo devuelven vistas. Solución: llama a.copy()antes de mutar los resultados filtrados. - Propagación de NaN -
np.mean([1, np.nan, 3])es NaN a menos que pasesnanmean. Solución: usanp.nanmeano enmascara primero. - Errores de broadcasting -
(3, 4) + (4,)funciona;(3, 4) + (3,)lanza un error a menos que cambies la forma. Solución: alinea conarr[:, np.newaxis]oreshape.
Alternativas
| Alternativa | Úsalo Cuando | No lo Uses Cuando |
|---|---|---|
| Listas de Python | Secuencias pequeñas, objetos heterogéneos | Transformaciones numéricas de un millón de elementos |
| Series de pandas | Datos 1-D etiquetados con valores faltantes | Álgebra lineal cruda en buffers sin etiquetas |
| Series de Polars | Pipelines columnares perezosos a escala | Solo necesitas una ufunc rápida de NumPy |
Módulo array (stdlib) | Arrays numéricos tipados sin dependencia de NumPy | Necesitas broadcasting o álgebra lineal |
Preguntas Frecuentes
¿Por qué los arrays de NumPy deben ser homogéneos?
- Un único dtype permite a NumPy almacenar datos de forma contigua y vectorizar en C.
- Los objetos de Python mixtos residen en un array de tipo objeto - más lento y sin aceleración de ufunc.
¿Cuándo copia el broadcasting los datos?
- El broadcasting crea una forma virtual expandida a través de pasos (strides) - ninguna copia hasta que se materializa con
np.broadcast_to(...).copy(). - Escribir a través de una vista transmitida puede corromper el buffer subyacente.
¿Cómo elijo entre float32 y float64?
- Usa
float32para tensores grandes donde ~7 dígitos decimales son suficientes. - Usa
float64para agregados financieros a menos que tengas una ganancia de memoria medida.
¿Qué reemplazó a np.random.seed?
import numpy as np
rng = np.random.default_rng(42)
rng.integers(0, 100, size=5)default_rnges la API moderna y estadísticamente más segura.
¿Cómo sumo sin desbordamiento en columnas int32?
- Convierte a
int64antes desum:arr.astype(np.int64).sum(). - O usa
np.sum(arr, dtype=np.int64).
¿Puedo usar cadenas de NumPy para análisis de texto?
- Existen dtypes de
np.str_de ancho fijo, pero pandas/Polars manejan el texto mejor. - Usa NumPy para kernels numéricos; delega las cadenas a las bibliotecas de DataFrames.
¿Por qué mi máscara booleana tiene la forma incorrecta?
- Las máscaras deben hacer broadcasting a la forma del array: una máscara
(n,)en(n, m)necesita(n, 1). - Usa
mask[:, np.newaxis]onp.broadcast_to.
¿Cómo evito modificar una vista?
safe = arr[mask].copy()
safe *= 2 # no toca arr¿Es np.dot lo mismo que @?
- Para arrays 2-D,
@ynp.dotson multiplicación de matrices. - Para dimensiones superiores,
@sigue las reglas de apilamiento de PEP 465 - prefiere@por claridad.
¿Cómo mido el tiempo de NumPy frente a Python puro?
- Usa
timeiten tamaños de array que procesas realmente. npequeños cruzan el punto donde las listas de Python ganan debido a la sobrecarga de creación.
Relacionado
- Indexación y Reestructuración de NumPy - slices, indexado fancy, ejes
- Series y DataFrames de pandas - tablas etiquetadas construidas sobre NumPy
- Rendimiento y Memoria - reducción de dtype y fragmentación
- Conceptos Básicos de Análisis de Datos - primer recorrido de análisis
Versiones de la pila: Esta página fue escrita para Python 3.14.0 (estable 3.14, mantenimiento 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, y uv 0.6+.