kali_the_dog
kali_the_dog

Reputation: 21

Entering values in a 2-D array in Python

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?

Upvotes: 2

Views: 86

Answers (3)

Divakar
Divakar

Reputation: 221564

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)

Upvotes: 0

Zach P
Zach P

Reputation: 1791

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)]

Upvotes: 0

Itay
Itay

Reputation: 16777

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)

Upvotes: 1

Related Questions