2
for i in range(limit_1):
    for j in range(limit_2):
        a[i][j]=np.sqrt(np.absolute(b[i])**2+np.absolute(c[j])**2)

Is there an alternative way to perform this task, using perhaps a numpy function?

2
  • 1
    can you show how should look the expected array? Commented Nov 2, 2016 at 6:50
  • @RomanPerekhrest : the array should be 2x2 array with elements a[i][j] given by the expression in the for loop Commented Nov 2, 2016 at 6:58

3 Answers 3

1

Your original code:

limit_1 = 4
limit_2 = 3

import numpy as np
a = np.zeros([limit_1, limit_2])
b = np.array([1, -6, 7, 3])
c = np.array([3, 2, -1])

print("Original:")
for i in range(limit_1):
    for j in range(limit_2):
        a[i][j]=np.sqrt(np.absolute(b[i])**2+np.absolute(c[j])**2)

print(a)

Outputs:

Original:
[[ 3.16227766  2.23606798  1.41421356]
 [ 6.70820393  6.32455532  6.08276253]
 [ 7.61577311  7.28010989  7.07106781]
 [ 4.24264069  3.60555128  3.16227766]]

And the shortened version:

print("Improved:")
a = np.sqrt(
        np.tile(np.array([b]).transpose(), (1, limit_2)) ** 2 +\
        np.tile(np.array(c).transpose(), (limit_1, 1)) ** 2)

print(a)

Outputs:

Improved:
[[ 3.16227766  2.23606798  1.41421356]
 [ 6.70820393  6.32455532  6.08276253]
 [ 7.61577311  7.28010989  7.07106781]
 [ 4.24264069  3.60555128  3.16227766]]

Explanation

First we stretch the vector column b to a matrix (and then take it's 2nd power):

>>> np.tile(np.array([b]).transpose(), (1, limit_2))
array([[ 1,  1,  1],
       [-6, -6, -6],
       [ 7,  7,  7],
       [ 3,  3,  3]])

>>> np.tile(np.array([b]).transpose(), (1, limit_2)) ** 2
array([[ 1,  1,  1],
       [36, 36, 36],
       [49, 49, 49],
       [ 9,  9,  9]])

Then we do the same for the row column c:

>>> np.tile(np.array(c).transpose(), (limit_1, 1))
array([[ 3,  2, -1],
       [ 3,  2, -1],
       [ 3,  2, -1],
       [ 3,  2, -1]])
>>> np.tile(np.array(c).transpose(), (limit_1, 1)) ** 2
array([[9, 4, 1],
       [9, 4, 1],
       [9, 4, 1],
       [9, 4, 1]])

We then sum them together and calculate the root.


P.S. 1 - I used only the squared power instead of the absolute value, but if you still need the absolute value you can use it the same way.

P.S. 2 - Notice that the calculation can be done more efficient, i.e calculate the power before we tile the arrays, but this way is more clearer for this post)

Sign up to request clarification or add additional context in comments.

Comments

0

Note that there is no point of squaring the absolute value as n**2 and abs(n)**2 are exactly the same.

Either way, using list comprehension:

temp = [math.sqrt(numpy.absolute(x)**2 + numpy.absolute(y)**2) for x in b for y in c]
a = [temp[x:x+limit_2] for x in range(0, len(temp), limit_2)]

2 Comments

The elements of the array in my case can also be complex
@PrishChakraborty Either way, this solution should work
0

You could use broadcasting by extending b from 1D to 2D by introducing a new singleton axis as the second axis with np.newaxis/None and then perform operations against c. This would simplify things there and also achieved a vectorized method, like so -

np.sqrt(np.abs(b[:,None])**2 + np.abs(c)**2)

As also talked about in the other answers that since squaring would inherently produce non-negative numbers, so we can just skip the absolute operation, to give us -

np.sqrt(b[:,None]**2 + c**2)

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.