The Python Oracle

Numpy: Divide each row by a vector element

Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: Life in a Drop

--

Chapters
00:00 Question
00:45 Accepted answer (Score 257)
01:06 Answer 2 (Score 19)
01:44 Answer 3 (Score 8)
02:12 Answer 4 (Score 7)
02:52 Thank you

--

Full question
https://stackoverflow.com/questions/1960...

Answer 1 links:
http://docs.scipy.org/doc/numpy/user/bas...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #arrays #numpy #scipy

#avk47



ACCEPTED ANSWER

Score 265


Here you go. You just need to use None (or alternatively np.newaxis) combined with broadcasting:

In [6]: data - vector[:,None]
Out[6]:
array([[0, 0, 0],
       [0, 0, 0],
       [0, 0, 0]])

In [7]: data / vector[:,None]
Out[7]:
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])



ANSWER 2

Score 19


As has been mentioned, slicing with None or with np.newaxes is a great way to do this. Another alternative is to use transposes and broadcasting, as in

(data.T - vector).T

and

(data.T / vector).T

For higher dimensional arrays you may want to use the swapaxes method of NumPy arrays or the NumPy rollaxis function. There really are a lot of ways to do this.

For a fuller explanation of broadcasting, see http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html




ANSWER 3

Score 9


Pythonic way to do this is ...

np.divide(data.T,vector).T

This takes care of reshaping and also the results are in floating point format. In other answers results are in rounded integer format.

#NOTE: No of columns in both data and vector should match




ANSWER 4

Score 4


JoshAdel's solution uses np.newaxis to add a dimension. An alternative is to use reshape() to align the dimensions in preparation for broadcasting.

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

data
# array([[1, 1, 1],
#        [2, 2, 2],
#        [3, 3, 3]])
vector
# array([1, 2, 3])

data.shape
# (3, 3)
vector.shape
# (3,)

data / vector.reshape((3,1))
# array([[1, 1, 1],
#        [1, 1, 1],
#        [1, 1, 1]])

Performing the reshape() allows the dimensions to line up for broadcasting:

data:            3 x 3
vector:              3
vector reshaped: 3 x 1

Note that data/vector is ok, but it doesn't get you the answer that you want. It divides each column of array (instead of each row) by each corresponding element of vector. It's what you would get if you explicitly reshaped vector to be 1x3 instead of 3x1.

data / vector
# array([[1, 0, 0],
#        [2, 1, 0],
#        [3, 1, 1]])
data / vector.reshape((1,3))
# array([[1, 0, 0],
#        [2, 1, 0],
#        [3, 1, 1]])