element wise multiplication of a vector and a matrix with numpy - python

Given python code with numpy:
import numpy as np
a = np.arange(6).reshape(3, 2) # a = [[0, 1], [2, 3], [4, 5]]; a.shape = (3, 2)
b = np.arange(3) + 1 # b = [1, 2, 3] ; b.shape = (3,)
How can I multiply each value in b with each corresponding row ('vector') in a? So here, I want the result as:
result = [[0, 1], [4, 6], [12, 15]] # result.shape = (3, 2)
I can do this with a loop, but I am wondering about a vectorized approach. I found an Octave solution here. Apart from this, I didn't find anything else. Any pointers for this?
Thank you in advance.

Probably the simplest is to do the following.
import numpy as np
a = np.arange(6).reshape(3, 2) # a = [[0, 1], [2, 3], [4, 5]]; a.shape = (3, 2)
b = np.arange(3) + 1
ans = np.diag(b)#a
Here's a method that exploits numpy multiplication broadcasting:
ans = (b*a.T).T
These two solutions basically take the same approach
ans = np.tile(b,(2,1)).T*a
ans = np.vstack([b for _ in range(a.shape[1])]).T*a

In [123]: a = np.arange(6).reshape(3, 2) # a = [[0, 1], [2, 3], [4, 5]]; a.
...: shape = (3, 2)
...: b = np.arange(3) + 1 # b = [1, 2, 3] ; b.
...: shape = (3,)
In [124]: a
Out[124]:
array([[0, 1],
[2, 3],
[4, 5]])
A (3,1) will multiply a (3,2) via broadcasting:
In [125]: a*b[:,None]
Out[125]:
array([[ 0, 1],
[ 4, 6],
[12, 15]])

Related

Multiply Numpy arrays of different sizes

I have a list of coefficients and a list of times
a = np.array([0,1,2,3])
t = np.array([1,2,3])
I would like to perform some multiplicative operation on the two where each coefficient is multiplied by each of the times to result in an array like:
array([[0, 0, 0],
[1, 2, 3],
[2, 4, 6],
[3, 6, 9]])
I can do this with a for loop like:
np.array([i * t for i in a])
However I was wondering whether there was a more efficient numpythonic way of performing this operation without the for loop as in reality I have much bigger arrays and multiple sets of coefficients?
Try this (uses broadcasting).
>>> import numpy as np
>>> a = np.array([0, 1, 2, 3])
>>> t = np.array([1, 2, 3])
>>> res1 = t * a[:, None]
>>> res1
array([[0, 0, 0],
[1, 2, 3],
[2, 4, 6],
[3, 6, 9]])
My prefered way is:
a[:, None] * t
But there is also a special method for that:
np.outer(a, t)

Creating an array element-wise from product of two arrays

I have a project wherein, after multiplying arrays, I have to arrange them into a separate array (element-wise) and get their sums.
As an example:
a = [1, 0, 1]
b = [[3,5,2], [5,4,3], [5,2,2]]
c = a*b
c = [ [3, 5, 2]
[0, 0, 0]
[5, 2, 2] ]
Now, I want to put the answers in an individual array element wise such as:
r1 = [3, 0, 5]
r2 = [5, 0, 2]
r3 = [2, 0, 2]
Then, get its sum.
sum_r1 = [8]
sum_r2 = [7]
sum_r3 = [4]
So far, my I am only able to code the multiplication. I am still trying the appropriate code for the succeeding steps. My code looks like this:
[EDIT]
def fitness_score(a, b):
c = numpy.multiply(a, b)
trns = numpy.transpose(c)
s = numpy.sum(trns, axis=1)
return s
Output gives the answer but it has an error something like this: ValueError: operands could not be broadcast together with shapes (500,3) (3,3). Note that the values in a are obtained randomly.
Any help would be appreciated! Thank you in advance!
You can use NumPy, just use transpose on the second matrix to get the desired result.
import numpy as np
a = [1, 0, 1]
b = [[3,5,2], [5,4,3], [5,2,2]]
a = np.array(a)
b = np.array(b)
mul = a*b.T
#array([[3, 0, 5],
# [5, 0, 2],
# [2, 0, 2]])
s = np.sum(a*b.T, axis=1)
#array([8, 7, 4])
If you have a 500 by 3 shaped array for a. You can try this:
import numpy as np
a = [[1, 0, 1] for _ in range(500)]
b = [[3,5,2], [5,4,3], [5,2,2]]
a = np.array(a)
b = np.array(b)
mul = [a_c*b.T for a_c in a]
#array([[3, 0, 5],
# [5, 0, 2],
# [2, 0, 2]])
s = np.sum(mul, axis=-1)
print(s)

how to implement multiple ifelse in numpy

I have an array like this and need to replace every 1 with 2, every 3 with 4, every 4 with 1. Is there a way to do this just with np and not loops?
import numpy as np
np.random.seed(2)
arr=np.random.randint(1,5,(3,3),int)
arr
array([[1, 4, 2],
[1, 3, 4],
[3, 4, 1]])
If I use array mask sequentially, it doesn't give the expected outcome:
array([[2, 1, 2],
[2, 4, 1],
[4, 1, 2]])
It is based on a conditional logic and not maths formula
If the array values don't necessarely range between 1 and 4 you can use np.select:
import numpy as np
a = np.random.randint(1,5, (3,3))
condlist = [np.logical_or(a==1, a==2), a==3, a==4]
choicelist= [2, 4, 1]
b = np.select(condlist, choicelist)
which does not care about the order of the conditions
Here's one with np.searchsorted for performance efficiency -
def map_values(arr, old_val, new_val):
sidx = old_val.argsort()
idx = np.searchsorted(old_val,arr,sorter=sidx)
return np.where(old_val[idx]==arr, new_val[sidx[idx]], arr)
Sample run -
In [40]: arr
Out[40]:
array([[1, 4, 2],
[1, 3, 4],
[3, 4, 1]])
In [41]: old_val = np.array([1,3,4])
...: new_val = np.array([2,4,1])
In [42]: map_values(arr, old_val, new_val)
Out[42]:
array([[2, 1, 2],
[2, 4, 1],
[4, 1, 2]])
Could do this with a lambda function and np.vectorize():
import numpy as np
np.random.seed(2)
arr=np.random.randint(1,5,(3,3),int)
f = lambda x: x%4 + 1 if x in [1,3,4] else x
vfunc = np.vectorize(f)
Usage:
>>> vfunc(arr)
array([[2, 1, 2],
[2, 4, 1],
[4, 1, 2]])
You have to be careful about the order of assignments. For example, if you do
arr[arr == 4] = 1
arr[arr == 1] = 2
Now all of the elements that were originally 4 will be 2, not 1 as you intend.
One solution is to carefully craft the order of assignments:
arr[arr == 1] = 2
arr[arr == 4] = 1
However, this is very brittle and will fall apart as you introduce more of them. It would be better to create the masks up front from the original array:
ones = arr == 1
fours = arr == 4
arr[ones] = 2
arr[fours] = 1
Now the order of the assignments won't matter because the masks are determined before modifying the array.
You want arr % 4 + 1, except in the case of 2, which stays the same. So use np.where to find all the 2s. Then do arr % 4 + 1, then reset all the 2s.
import numpy as np
np.random.seed(2)
arr=np.random.randint(1,5,(3,3),int)
twos = np.where(arr == 2)
arr = arr % 4 + 1
arr[twos] = 2
print(arr)

Numpy: how delete rows common to 2 matrices

problem is very simple: I have two 2d np.array and I want to get a third array that only contains the rows that are not in common with the latter twos.
for example:
X = np.array([[0,1],[1,2],[4,5],[5,6],[8,9],[9,10]])
Y = np.array([[5,6],[9,10]])
Z = function(X,Y)
Z = array([[0, 1],
[1, 2],
[4, 5],
[8, 9]])
I tried np.delete(X,Y,axis=0) but it doesn't work...
Z = np.vstack(row for row in X if row not in Y)
The numpy_indexed package (disclaimer: I am its author) extends the standard numpy array set operations to multi-dimensional use cases such as these, with good efficiency:
import numpy_indexed as npi
Z = npi.difference(X, Y)
Here's a views based approach -
# Based on http://stackoverflow.com/a/41417343/3293881 by #Eric
def setdiff2d(a, b):
# check that casting to void will create equal size elements
assert a.shape[1:] == b.shape[1:]
assert a.dtype == b.dtype
# compute dtypes
void_dt = np.dtype((np.void, a.dtype.itemsize * np.prod(a.shape[1:])))
orig_dt = np.dtype((a.dtype, a.shape[1:]))
# convert to 1d void arrays
a = np.ascontiguousarray(a)
b = np.ascontiguousarray(b)
a_void = a.reshape(a.shape[0], -1).view(void_dt)
b_void = b.reshape(b.shape[0], -1).view(void_dt)
# Get indices in a that are also in b
return np.setdiff1d(a_void, b_void).view(orig_dt)
Sample run -
In [81]: X
Out[81]:
array([[ 0, 1],
[ 1, 2],
[ 4, 5],
[ 5, 6],
[ 8, 9],
[ 9, 10]])
In [82]: Y
Out[82]:
array([[ 5, 6],
[ 9, 10]])
In [83]: setdiff2d(X,Y)
Out[83]:
array([[0, 1],
[1, 2],
[4, 5],
[8, 9]])
Z = np.unique([tuple(row) for row in X + Y])

numpy matrix arithmetic with its diagonal element

I love numpy because it allows vectorized operation such as:
mat1 = np.array([[1,2],[3,4]])
mat2 = np.array([[10,20],[30,40]])
mat3 = (mat1 + mat2)*2.0 # vectorization way. nice.
But, I can not find how to do this kind of operation with diagonal elements. What I'd like to do is
Is it possible to operate above in a vectorization way with numpy?
For the first exemple :
With :
In [3]: A
"""
array([[1, 3, 4, 0, 4],
[2, 3, 3, 3, 0],
[1, 0, 4, 1, 0],
[0, 3, 3, 2, 0],
[2, 1, 0, 3, 2]])
"""
In [4]: Aii=vstack((diag(A),)*A.shape[0])
"""
array([[1, 3, 4, 2, 2],
[1, 3, 4, 2, 2],
[1, 3, 4, 2, 2],
[1, 3, 4, 2, 2],
[1, 3, 4, 2, 2]])
"""
In [5]: Ajj=Aii.T # transpose
In [6]: B= 1/ (Aii+Ajj-2*A)
Or, with more abstract tools :
B1 = 1 / (np.add.outer(diag(A),diag(A))-2*A)
B2 = A / np.sqrt(np.multiply.outer(diag(A),diag(A)))
For cases like those with no dependency between iterations, broadcasting seems like the obvious approach after extending the dimensions of the diagonal 1D array to a 2D version with None/np.newaxis and performing the computations with its 1D version to simulate A[i,i] and A[j,j] respectively. Thus, to solve those two cases, one could proceed like so -
Ad = np.diag(A)
case1_out_vectorized = 1/(Ad[:,None] + Ad - 2*A)
case2_out_vectorized = A/np.sqrt(Ad[:,None]*Ad)
Sample run -
In [33]: # Random input array
...: A = np.random.rand(4,4)
...:
...: # Naive loopy implmentation (used here for verification)
...: m = A.shape[0]
...: case1_out_loopy = np.zeros((m,m))
...: case2_out_loopy = np.zeros((m,m))
...: for i in range(m):
...: for j in range(m):
...: case1_out_loopy[i,j] = 1/(A[i,i] + A[j,j] - 2*A[i,j])
...: case2_out_loopy[i,j] = A[i,j]/np.sqrt(A[i,i]*A[j,j])
...:
In [34]: # Proposed approach
...: Ad = np.diag(A)
...: case1_out_vectorized = 1/(Ad[:,None] + Ad - 2*A)
...: case2_out_vectorized = A/np.sqrt(Ad[:,None]*Ad)
...:
In [35]: np.allclose(case1_out_loopy,case1_out_vectorized)
Out[35]: True
In [36]: np.allclose(case2_out_loopy,case2_out_vectorized)
Out[36]: True

Categories

Resources