Divide every element in a row by that row's sum so each row sums to 1. This is a common pre-processing step: once every row is a probability vector, rows from different datasets become comparable.

By hand

Loop over the 2×3 dataset one row at a time. Compute row_sum with the built-in sum, then divide each element and collect the result.

naive.py
Replay: real traced execution (multi-file project)
data = [[3, 3, 6], [4, 2, 2]]
result = []
for row in data:
    row_sum = sum(row)
    norm_row = [v / row_sum for v in row]
    result.append(norm_row)
print('RESULT:', [[round(v, 10) for v in row] for row in result])
  1. data ← [[3, 3, 6], [4, 2, 2]]

    1data = [[3, 3, 6], [4, 2, 2]]2result = []
    values this step[[3, 3, 6], [4, 2, 2]]data
  2. result ← []

    1data = [[3, 3, 6], [4, 2, 2]]2result = []3for row in data:
    values this step[]result
  3. row ← [3, 3, 6]

    2result = []3for row in data:4    row_sum = sum(row)
    values this step[3, 3, 6]row
  4. row_sum ← 12

    3for row in data:4    row_sum = sum(row)5    norm_row = [v / row_sum for v in row]
    values this step12row_sum
  5. norm_row ← [0.25, 0.25, 0.5]

    4row_sum = sum(row)5norm_row = [v / row_sum for v in row]6result.append(norm_row)
    values this step[0.25, 0.25, 0.5]norm_row
  6. result ← [[0.25, 0.25, 0.5]]

    5    norm_row = [v / row_sum for v in row]6    result.append(norm_row)7print('RESULT:', [[round(v, 10) for v in row] for row in result])
    values this step[] [[0.25, 0.25, 0.5]]result
  7. row ← [4, 2, 2]

    2result = []3for row in data:4    row_sum = sum(row)
    values this step[3, 3, 6] [4, 2, 2]row
  8. row_sum ← 8

    3for row in data:4    row_sum = sum(row)5    norm_row = [v / row_sum for v in row]
    values this step12 8row_sum
  9. norm_row ← [0.5, 0.25, 0.25]

    4row_sum = sum(row)5norm_row = [v / row_sum for v in row]6result.append(norm_row)
    values this step[0.25, 0.25, 0.5] [0.5, 0.25, 0.25]norm_row
  10. result ← [[0.25, 0.25, 0.5], [0.5, 0.25, 0.25]]

    5    norm_row = [v / row_sum for v in row]6    result.append(norm_row)7print('RESULT:', [[round(v, 10) for v in row] for row in result])
    values this step[[0.25, 0.25, 0.5]] [[0.25, 0.25, 0.5], [0.5, 0.25, 0.25]]result
  11. for row in data:

    2result = []3for row in data:4    row_sum = sum(row)
  12. stdout ← RESULT: [[0.25, 0.25, 0.5], [0.5, 0.25, 0.25]]

    6    result.append(norm_row)7print('RESULT:', [[round(v, 10) for v in row] for row in result])
    values this stepRESULT: [[0.25, 0.25, 0.5], [0.5, 0.25, 0.25]]stdout

With NumPy

np.array stores the matrix in a typed buffer. sum(axis=1, keepdims=True) produces a (2, 1) column vector of row sums; dividing the (2, 3) matrix by this (2, 1) vector broadcasts automatically — NumPy aligns the singleton dimension and repeats the division across all three columns without an explicit loop. The snapshot shows row_sums and the normalized result.

library.py
import numpy as np

data = np.array([[3, 3, 6], [4, 2, 2]], dtype=float)
row_sums = data.sum(axis=1, keepdims=True)
result = data / row_sums
rv = [[round(v, 10) for v in row] for row in result.tolist()]
print('row_sums: shape:', row_sums.shape, 'dtype:', row_sums.dtype, 'values:', row_sums.tolist())
print('result: shape:', result.shape, 'dtype:', result.dtype)
print('result values:', rv)
print('RESULT:', rv)
row_sums: shape: (2, 1) dtype: float64 values: [[12.0], [8.0]]
result: shape: (2, 3) dtype: float64
result values: [[0.25, 0.25, 0.5], [0.5, 0.25, 0.25]]
RESULT: [[0.25, 0.25, 0.5], [0.5, 0.25, 0.25]]

Implementation notes

  • keepdims=True preserves the reduced axis as a size-1 dimension, giving shape (2, 1) instead of (2,). Without it, broadcasting would fail: a (2,) vector cannot be divided into a (2, 3) matrix along the row axis.
  • This is the column-broadcast pattern: the (2, 1) column vector broadcasts across all 3 columns of a, applying a different divisor to each row.
  • After normalization, each row sums to 1.0 (within floating-point precision), making each row a probability vector.
  • The next step in standardization is z-scoring: subtract the column mean (see center-columns) and divide by the column standard deviation — that lesson is in the roadmap statistics chapter.
  • Shape, dtype, and values are shown explicitly here because ndarray.__repr__ output varies with NumPy version and print options.