7

I have a numpy array of 2D vectors, which I am trying to normalize as below. The array can have vectors with magnitude zero.

x = np.array([[0.0, 0.0], [1.0, 0.0]])
norms = np.array([np.linalg.norm(a) for a in x])

>>> x/norms
array([[ nan,   0.],
       [ inf,   0.]])

>>> nonzero = norms > 0.0
>>> nonzero
array([False,  True], dtype=bool)

Can I somehow use nonzero to apply the division only to x[i] such that nonzero[i] is True? (I can write a loop for this - just wondering if there's a numpy way of doing this)

Or is there a better way of normalizing the array of vectors, skipping all zero vectors in the process?

1
  • np.linalp.norm has a second argument axis you can use to increase speed, as discussed here: stackoverflow.com/a/19794741/1959808 Commented Nov 18, 2013 at 9:10

3 Answers 3

8

If you can do the normalization in place, you can use your boolean indexing array like this:

nonzero = norms > 0
x[nonzero] /= norms[nonzero]
Sign up to request clarification or add additional context in comments.

Comments

2

Here's one possible way of doing this

norms = np.sqrt((x**2).sum(axis=1,keepdims=True))
x[:] = np.where(norms!=0,x/norms,0.)

This uses np.where to do the substitution you need.

Note: in this case x is modified in place.

2 Comments

+1 Beat me toit by a few seconds! To do it in place I think it is better to use a boolean indexing array: idx = (norms != 0); x[idx] /= norms[idx]
@Jaime - thanks! Please post it as an answer so I can give you credit.
1

It's probably easiest just to do the calculation and then modify the results to be what you'd like:

y = x/norms
y[np.isnan(y) | np.isinf(y)]=0

#y = array([[ 0.,  0.],
#       [ 0.,  0.]])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.