Python NumPy: How to Divide Each Row by a Vector in NumPy
Row-wise division is common in data normalization and scaling operations. NumPy's broadcasting rules require reshaping 1D vectors to column vectors for proper alignment with 2D matrices.
The Problem
When dividing a matrix by a vector, you need each row divided by a corresponding value:
import numpy as np
matrix = np.array([
[10, 20, 30],
[40, 50, 60]
])
divisors = np.array([10, 5]) # Row 0 ÷ 10, Row 1 ÷ 5
# This fails!
try:
result = matrix / divisors
except ValueError as e:
print(f"Error: {e}")
# Error: operands could not be broadcast together with shapes (2,3) (2,)
Output:
Error: operands could not be broadcast together with shapes (2,3) (2,)
The shapes don't align for broadcasting because NumPy tries to match from the right.
The Solution: Using np.newaxis
Reshape the divisor vector to a column vector with [:, np.newaxis]:
import numpy as np
matrix = np.array([
[10, 20, 30],
[40, 50, 60]
])
divisors = np.array([10, 5])
# Reshape divisors to column vector (2, 1)
result = matrix / divisors[:, np.newaxis]
print(result)
Output:
[[ 1. 2. 3.]
[ 8. 10. 12.]]
Step-by-Step Breakdown
import numpy as np
matrix = np.array([[10, 20, 30],
[40, 50, 60]])
divisors = np.array([10, 5])
print(f"Matrix shape: {matrix.shape}") # (2, 3)
print(f"Divisors shape: {divisors.shape}") # (2,)
# Reshape divisors to column vector
column_divisors = divisors[:, np.newaxis]
print(f"Column divisors shape: {column_divisors.shape}") # (2, 1)
print(f"Column divisors:\n{column_divisors}")
# [[10]
# [ 5]]
# Now broadcasting works:
# (2, 3) / (2, 1) → (2, 3)
result = matrix / column_divisors
print(f"Result:\n{result}")
Output:
Matrix shape: (2, 3)
Divisors shape: (2,)
Column divisors shape: (2, 1)
Understanding Broadcasting
Broadcasting aligns shapes from the right. For row-wise operations, the divisor needs a trailing dimension of 1:
| Array | Shape | Alignment |
|---|---|---|
matrix | (2, 3) | 2 × 3 |
divisors | (2,) | ? × 2 ❌ |
divisors[:, np.newaxis] | (2, 1) | 2 × 1 ✅ |
import numpy as np
# Visualizing the broadcast
matrix = np.array([[10, 20, 30],
[40, 50, 60]])
divisors = np.array([[10], # Broadcasts across row 0
[5]]) # Broadcasts across row 1
print("Matrix:")
print(matrix)
print("\nDivisors:")
print(divisors)
result = matrix / divisors # Broadcasting happens here
print("\nResult:")
print(result)
# Effectively becomes:
# [[10, 20, 30] [[10, 10, 10] [[ 1., 2., 3.]
# [40, 50, 60]] / [ 5, 5, 5]] = [ 8., 10., 12.]]
Output:
Matrix:
[[10 20 30]
[40 50 60]]
Divisors:
[[10]
[ 5]]
Result:
[[ 1. 2. 3.]
[ 8. 10. 12.]]
Alternative: Using reshape()
reshape(-1, 1) achieves the same result:
import numpy as np
matrix = np.array([[10, 20, 30],
[40, 50, 60]])
divisors = np.array([10, 5])
# Using reshape
result = matrix / divisors.reshape(-1, 1)
print(result)
Output:
[[ 1. 2. 3.]
[ 8. 10. 12.]]
Alternative: Using None
None is an alias for np.newaxis:
import numpy as np
matrix = np.array([[10, 20, 30],
[40, 50, 60]])
divisors = np.array([10, 5])
# None works the same as np.newaxis
result = matrix / divisors[:, None]
print(result)
Output:
[[ 1. 2. 3.]
[ 8. 10. 12.]]
Use None for brevity in quick scripts, but np.newaxis is more explicit and readable in production code.
Row-wise vs Column-wise Operations
Understanding the difference helps avoid confusion:
import numpy as np
matrix = np.array([[10, 20, 30],
[40, 50, 60]])
row_divisors = np.array([10, 5]) # 2 values (one per row)
col_divisors = np.array([10, 20, 30]) # 3 values (one per column)
# Row-wise: divide each row by its corresponding value
row_result = matrix / row_divisors[:, np.newaxis]
print("Row-wise division:")
print(row_result)
# Column-wise: divide each column by its corresponding value
col_result = matrix / col_divisors # No reshape needed!
print("\nColumn-wise division:")
print(col_result)
Output:
Row-wise division:
[[ 1. 2. 3.]
[ 8. 10. 12.]]
Column-wise division:
[[1. 1. 1. ]
[4. 2.5 2. ]]
Practical Examples
Normalizing Rows by Their Sum
import numpy as np
data = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
# Calculate sum of each row
row_sums = data.sum(axis=1)
print(f"Row sums: {row_sums}")
# Normalize each row
normalized = data / row_sums[:, np.newaxis]
print("Normalized rows:")
print(normalized)
# Verify rows sum to 1
print(f"Row sums after normalization: {normalized.sum(axis=1)}")
Output:
Row sums: [ 6 15 24]
Normalized rows:
[[0.16666667 0.33333333 0.5 ]
[0.26666667 0.33333333 0.4 ]
[0.29166667 0.33333333 0.375 ]]
Row sums after normalization: [1. 1. 1.]
Dividing by Row Maximum
import numpy as np
data = np.array([
[10, 20, 30],
[5, 15, 25],
[100, 200, 150]
])
# Get max of each row
row_max = data.max(axis=1)
print(f"Row max: {row_max}")
# Scale each row to [0, 1] range
scaled = data / row_max[:, np.newaxis]
print("Scaled by row max:")
print(scaled)
Output:
Row max: [ 30 25 200]
Scaled by row max:
[[0.33333333 0.66666667 1. ]
[0.2 0.6 1. ]
[0.5 1. 0.75 ]]
Z-Score Normalization by Row
import numpy as np
data = np.array([
[10, 20, 30],
[100, 200, 300],
[5, 10, 15]
])
# Calculate row means and standard deviations
row_means = data.mean(axis=1)
row_stds = data.std(axis=1)
# Z-score normalize each row
z_scores = (data - row_means[:, np.newaxis]) / row_stds[:, np.newaxis]
print("Z-scores by row:")
print(z_scores)
Output:
Z-scores by row:
[[-1.22474487 0. 1.22474487]
[-1.22474487 0. 1.22474487]
[-1.22474487 0. 1.22474487]]
Other Row-wise Operations
The same pattern works for other operations:
import numpy as np
matrix = np.array([[10, 20, 30],
[40, 50, 60]])
row_values = np.array([5, 10])
# Row-wise addition
print(matrix + row_values[:, np.newaxis])
# Row-wise subtraction
print(matrix - row_values[:, np.newaxis])
# Row-wise multiplication
print(matrix * row_values[:, np.newaxis])
Output:
[[15 25 35]
[50 60 70]]
[[ 5 15 25]
[30 40 50]]
[[ 50 100 150]
[400 500 600]]
Quick Reference
| Operation | Vector Shape | Code |
|---|---|---|
| Divide each row | (n_rows,) → (n_rows, 1) | matrix / vec[:, np.newaxis] |
| Divide each column | (n_cols,) | matrix / vec (no reshape) |
| Scalar division | () | matrix / scalar |
Summary
Use vector[:, np.newaxis] or vector.reshape(-1, 1) to convert a 1D array into a column vector for row-wise operations.
This aligns the shapes for NumPy broadcasting, allowing each row to be divided (or multiplied, added, etc.) by its corresponding value in the vector.