Reputation: 21
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
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
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
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]]
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