numpy divide row by row sum

PythonMultidimensional ArrayNumpy

Python Problem Overview


How can I divide a numpy array row by the sum of all values in this row?

This is one example. But I'm pretty sure there is a fancy and much more efficient way of doing this:

import numpy as np
e = np.array([[0., 1.],[2., 4.],[1., 5.]])
for row in xrange(e.shape[0]):
    e[row] /= np.sum(e[row])

Result:

array([[ 0.        ,  1.        ],
       [ 0.33333333,  0.66666667],
       [ 0.16666667,  0.83333333]])

Python Solutions


Solution 1 - Python

Method #1: use None (or np.newaxis) to add an extra dimension so that broadcasting will behave:

>>> e
array([[ 0.,  1.],
       [ 2.,  4.],
       [ 1.,  5.]])
>>> e/e.sum(axis=1)[:,None]
array([[ 0.        ,  1.        ],
       [ 0.33333333,  0.66666667],
       [ 0.16666667,  0.83333333]])

Method #2: go transpose-happy:

>>> (e.T/e.sum(axis=1)).T
array([[ 0.        ,  1.        ],
       [ 0.33333333,  0.66666667],
       [ 0.16666667,  0.83333333]])

(You can drop the axis= part for conciseness, if you want.)

Method #3: (promoted from Jaime's comment)

Use the keepdims argument on sum to preserve the dimension:

>>> e/e.sum(axis=1, keepdims=True)
array([[ 0.        ,  1.        ],
       [ 0.33333333,  0.66666667],
       [ 0.16666667,  0.83333333]])

Solution 2 - Python

You can do it mathematically as enter image description here.

Here, E is your original matrix and D is a diagonal matrix where each entry is the sum of the corresponding row in E. If you're lucky enough to have an invertible D, this is a pretty mathematically convenient way to do things.

In numpy:

import numpy as np

diagonal_entries = [sum(e[row]) for row in range(e.shape[0])]
D = np.diag(diagonal_entries)
D_inv = np.linalg.inv(D)
e = np.dot(e, D_inv)

Solution 3 - Python

You can also use reshape method of numpy as follows:

e = np.array([[0., 1.],[2., 4.],[1., 5.]])
e/=np.sum(e, axis=1).reshape(-1,1)
e

array([[0.        , 1.    ],
       [0.33333333, 0.66666667],
       [0.16666667, 0.83333333]])

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionStefan ProfanterView Question on Stackoverflow
Solution 1 - PythonDSMView Answer on Stackoverflow
Solution 2 - PythonAliView Answer on Stackoverflow
Solution 3 - Pythondipankar1234View Answer on Stackoverflow