Array calculations often combine values that live at different granularities, such as one price per product and one fee per row of records. NumPy broadcasting keeps that arithmetic in array form when the shapes describe how the smaller values should line up with the larger array.

NumPy compares dimensions from the right. Equal sizes match, and a size of 1 expands across the other side, so a (3,) price vector aligns with the columns of a (2, 3) units array while a (2, 1) fee column aligns with rows.

Shape checks belong near calculations that mix arrays from files, functions, or user input. np.broadcast_shapes() exposes the shape NumPy will use, and an incompatible row vector raises ValueError before it can produce a misleading total.

Steps to calculate with NumPy broadcasting:

  1. Create a script that multiplies a units matrix by product prices and adds one store fee per row.
    array-broadcast-calculate.py
    import numpy as np
     
    units = np.array([[3, 0, 2], [1, 4, 5]], dtype=np.float64)
    unit_prices = np.array([2.50, 4.00, 1.25])
    store_fee = np.array([1.00, 1.50])[:, np.newaxis]
     
    subtotal = units * unit_prices
    total = subtotal + store_fee
     
    print("units shape:", units.shape)
    print("unit prices shape:", unit_prices.shape)
    print("store fee shape:", store_fee.shape)
    print("broadcast shape:", np.broadcast_shapes(units.shape, unit_prices.shape, store_fee.shape))
    print("subtotal:")
    print(subtotal)
    print("total:")
    print(total)

    The price vector stays one-dimensional because its three values match the columns. The store fee becomes a two-dimensional column so each row receives one fee value.

  2. Run the script and verify that the broadcast shape matches the calculated arrays.
    $ python array-broadcast-calculate.py
    units shape: (2, 3)
    unit prices shape: (3,)
    store fee shape: (2, 1)
    broadcast shape: (2, 3)
    subtotal:
    [[ 7.5   0.    2.5 ]
     [ 2.5  16.    6.25]]
    total:
    [[ 8.5   1.    3.5 ]
     [ 4.   17.5   7.75]]

    The (3,) price vector matches the last dimension, and the (2, 1) fee column expands across the three product columns in each row.

  3. Check the row-vector failure before using one value per row.
    $ python - <<'PY'
    import numpy as np
    
    units = np.zeros((2, 3))
    row_fee = np.array([1.00, 1.50])
    
    try:
        units + row_fee
    except ValueError as error:
        print(error)
    print("fixed row shape:", row_fee[:, np.newaxis].shape)
    print("fixed broadcast shape:", np.broadcast_shapes(units.shape, row_fee[:, np.newaxis].shape))
    PY
    operands could not be broadcast together with shapes (2,3) (2,)
    fixed row shape: (2, 1)
    fixed broadcast shape: (2, 3)

    A (2,) vector tries to match the last dimension of a (2, 3) array. Use [:, np.newaxis] or reshape(-1, 1) when one value should apply to each row.
    Related: Reshape an array