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