Broadcasting en NumPy

Intermedio
NumPy
NumPy
Actualizado: 05/05/2026

Diagrama: tutorial-numpy-broadcasting

Qué es broadcasting

Cuando se realiza una operación entre dos arrays de NumPy con la misma forma, la operación se aplica elemento a elemento. Pero en la práctica es habitual operar arrays con formas distintas: sumar un escalar a una matriz, restar un vector fila a cada fila de una matriz o combinar un vector columna con un vector fila.

Broadcasting es el mecanismo que NumPy utiliza para hacer compatibles arrays de formas diferentes en una operación aritmética. En lugar de copiar datos para igualar las dimensiones, NumPy "estira" virtualmente el array más pequeño para que coincida con el mayor, sin consumir memoria adicional.

import numpy as np

# Escalar + array: el escalar se "estira" a [5, 5, 5]
a = np.array([1, 2, 3])
resultado = a + 5
print(resultado)  # [6 7 8]

Sin broadcasting, esta operación requeriría crear manualmente un array [5, 5, 5] para poder sumar elemento a elemento. NumPy lo hace de forma implícita y eficiente.

import numpy as np

# Matriz 2D + vector 1D
matriz = np.array([[10, 20, 30],
                    [40, 50, 60]])

descuento = np.array([1, 2, 3])

resultado = matriz - descuento
print(resultado)
# [[ 9 18 27]
#  [39 48 57]]

En este caso, el vector descuento de forma (3,) se alinea con la última dimensión de la matriz (2, 3). NumPy replica virtualmente el vector en cada fila para completar la operación.

Broadcasting no crea copias de los datos. NumPy ajusta los strides internos del array para simular la replicación, lo que mantiene el consumo de memoria constante independientemente del tamaño del array mayor.

Las tres reglas de broadcasting

NumPy aplica tres reglas secuenciales para determinar si dos arrays son compatibles para broadcasting. Si alguna regla no se cumple, la operación lanza un ValueError.

Regla 1: alineación de dimensiones. Si los arrays tienen distinto número de dimensiones, se añade un 1 a la izquierda de la forma del array con menos dimensiones hasta igualar el número de ejes.

Regla 2: compatibilidad por eje. Dos dimensiones son compatibles si tienen el mismo tamaño o si una de ellas vale 1.

Regla 3: expansión. La dimensión con valor 1 se "estira" para igualar la otra dimensión. El array resultante tiene la forma máxima en cada eje.

flowchart TD
    A["Array A shape: 4x3"] --- C{Comparar ejes}
    B["Array B shape: 1x3"] --- C
    C --> D["Eje 0: 4 vs 1<br>Compatible, se expande a 4"]
    C --> E["Eje 1: 3 vs 3<br>Compatible, mismo tamaño"]
    D --> F["Resultado shape: 4x3"]
    E --> F

Un ejemplo paso a paso con las reglas:

import numpy as np

# A tiene forma (4, 3), B tiene forma (3,)
A = np.ones((4, 3))
B = np.array([10, 20, 30])

# Regla 1: B pasa de (3,) a (1, 3) para igualar dimensiones
# Regla 2: eje 0 -> 4 vs 1, compatible; eje 1 -> 3 vs 3, compatible
# Regla 3: B se expande en eje 0 de 1 a 4

resultado = A + B
print(resultado.shape)  # (4, 3)
print(resultado)
# [[11. 21. 31.]
#  [11. 21. 31.]
#  [11. 21. 31.]
#  [11. 21. 31.]]

Cuando las formas no son compatibles, NumPy indica el error de forma explícita:

import numpy as np

A = np.ones((3, 4))
B = np.ones((3,))

# Regla 1: B pasa de (3,) a (1, 3)
# Regla 2: eje 1 -> 4 vs 3, NO compatible (ninguno es 1)
# resultado = A + B  # ValueError: operands could not be broadcast together

Tabla de compatibilidad

Algunos ejemplos de formas compatibles e incompatibles:

| Forma A | Forma B | Resultado | Compatible | |---------|---------|-----------|------------| | (5, 3) | (3,) | (5, 3) | Sí | | (5, 3) | (5, 1) | (5, 3) | Sí | | (1, 3) | (4, 1) | (4, 3) | Sí | | (3, 4) | (3,) | Error | No | | (2, 3) | (2,) | Error | No |

Patrones habituales de broadcasting

Escalar con array

El caso más simple. Un escalar tiene forma (), que se expande a cualquier dimensión.

import numpy as np

temperaturas = np.array([[15.2, 18.7, 22.1],
                          [14.8, 19.3, 21.5]])

# Convertir Celsius a Fahrenheit
fahrenheit = temperaturas * 9/5 + 32
print(fahrenheit)
# [[59.36 65.66 71.78]
#  [58.64 66.74 70.7 ]]

Vector fila con matriz

Un vector de forma (n,) se alinea con la última dimensión de la matriz. Es el patrón que se usa para operar sobre cada columna de forma uniforme.

import numpy as np

# Ventas trimestrales de 3 productos en 4 trimestres
ventas = np.array([[100, 150, 200, 180],
                    [90, 120, 160, 140],
                    [110, 130, 190, 170]])

# Ponderacion por trimestre
pesos = np.array([0.2, 0.25, 0.3, 0.25])

ventas_ponderadas = ventas * pesos
print(ventas_ponderadas)
# [[ 20.   37.5  60.   45. ]
#  [ 18.   30.   48.   35. ]
#  [ 22.   32.5  57.   42.5]]

Vector columna con vector fila

Al combinar un vector columna (m, 1) con un vector fila (n,), se genera una matriz (m, n). Este patrón es útil para crear tablas de operaciones.

import numpy as np

filas = np.array([1, 2, 3, 4]).reshape(4, 1)
columnas = np.array([10, 20, 30])

# Tabla de multiplicacion
tabla = filas * columnas
print(tabla)
# [[ 10  20  30]
#  [ 20  40  60]
#  [ 30  60  90]
#  [ 40  80 120]]

Aplicación práctica: normalización y centrado de datos

Broadcasting resulta especialmente útil en preprocesamiento de datos, donde es frecuente normalizar o centrar las columnas de un dataset. Estas operaciones requieren restar la media y dividir por la desviación típica de cada columna.

Centrado de datos

Centrar los datos consiste en restar la media de cada columna, de modo que cada variable tenga media cero.

import numpy as np

# Datos: 5 muestras, 3 variables
datos = np.array([[170, 65, 30],
                   [180, 80, 25],
                   [165, 55, 35],
                   [175, 70, 28],
                   [160, 50, 40]], dtype=float)

# Media por columna: shape (3,)
media = datos.mean(axis=0)
print(media)  # [170. 64. 31.6]

# Centrado: broadcasting resta (3,) a cada fila de (5, 3)
datos_centrados = datos - media
print(datos_centrados)
# [[  0.   1.  -1.6]
#  [ 10.  16.  -6.6]
#  [ -5.  -9.   3.4]
#  [  5.   6.  -3.6]
#  [-10. -14.   8.4]]

Normalización estándar (Z-score)

La normalización estándar transforma los datos para que tengan media 0 y desviación típica 1. Se utiliza habitualmente antes de alimentar modelos de machine learning.

import numpy as np

datos = np.array([[170, 65, 30],
                   [180, 80, 25],
                   [165, 55, 35],
                   [175, 70, 28],
                   [160, 50, 40]], dtype=float)

media = datos.mean(axis=0)       # shape (3,)
desviación = datos.std(axis=0)   # shape (3,)

# Normalizacion: dos operaciones de broadcasting encadenadas
datos_normalizados = (datos - media) / desviación
print(datos_normalizados.mean(axis=0).round(2))  # [0. 0. 0.]
print(datos_normalizados.std(axis=0).round(2))   # [1. 1. 1.]

Normalización min-max

Otra técnica frecuente escala los valores al rango [0, 1] utilizando el mínimo y máximo de cada columna.

import numpy as np

datos = np.array([[170, 65, 30],
                   [180, 80, 25],
                   [165, 55, 35],
                   [175, 70, 28],
                   [160, 50, 40]], dtype=float)

mínimos = datos.min(axis=0)   # shape (3,)
maximos = datos.max(axis=0)   # shape (3,)

# Broadcasting: (5,3) - (3,) / ((3,) - (3,))
datos_escalados = (datos - mínimos) / (maximos - mínimos)
print(datos_escalados)
# [[0.5        0.5        0.33333333]
#  [1.         1.         0.        ]
#  [0.25       0.16666667 0.66666667]
#  [0.75       0.66666667 0.2       ]
#  [0.         0.         1.        ]]

En estas normalizaciones, broadcasting evita escribir bucles sobre las columnas. La operación se expresa en una sola línea y se ejecuta con la misma eficiencia que si se hubiera escrito en C. Este patrón es exactamente lo que hace internamente StandardScaler o MinMaxScaler de scikit-learn.

Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, NumPy es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de NumPy

Explora más contenido relacionado con NumPy y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

Comprender el mecanismo de broadcasting en NumPy, aplicar las tres reglas de compatibilidad de formas y utilizar broadcasting en patrones habituales como normalización y centrado de datos.

Cursos que incluyen esta lección

Esta lección forma parte de los siguientes cursos estructurados con rutas de aprendizaje