Trouble vectorizing code - python

I'm having a hard time on doing this. I have two m x n matrices (A and B) and I need to multiply every column of A by the rows in B, to generate a m x (n*n) matrix. I guess I wasn't very clear in the explanation so I'll post an example:
A =
[1 2
3 4]
B =
[5 6
7 8]
I wish to have:
[[5 6] [10 12]
[21 24] [28 32]]
I was able to do it using for loops but I want to avoid for as much as possible. Also using numpy to all this and all data is stored as np.array.

Maybe:
>>> A = np.array([[1,2],[3,4]])
>>> B = np.array([[5,6],[7,8]])
>>> (A * B[None, :].T).T
array([[[ 5, 6],
[21, 24]],
[[10, 12],
[28, 32]]])
where we use None to add an extra dimension to B, and a few transpositions to get the alignment right.

If I understand you right, you want basic ( m * n ) multiplication right? Use numpy.dot():
>>> a = [[1, 0], [0, 1]]
>>> b = [[4, 1], [2, 2]]
>>> np.dot(a, b)
array([[4, 1],
[2, 2]])

Related

Use numpy to stack combinations of a 1D and 2D array

I have 2 numpy arrays, one 2D and the other 1D, for example like this:
import numpy as np
a = np.array(
[
[1, 2],
[3, 4],
[5, 6]
]
)
b = np.array(
[7, 8, 9, 10]
)
I want to get all possible combinations of the elements in a and b, treating a like a 1D array, so that it leaves the rows in a intact, but also joins the rows in a with the items in b. It would look something like this:
>>> combine1d(a, b)
[ [1 2 7] [1 2 8] [1 2 9] [1 2 10]
[3 4 7] [3 4 8] [3 4 9] [3 4 10]
[5 6 7] [5 6 8] [5 6 9] [5 6 10] ]
I know that there are slow solutions for this (like a for loop), but I need a fast solution to this as I am working with datasets with millions of integers.
Any ideas?
This is one of those cases where it's easier to build a higher dimensional object, and then fix the axes when you're done. The first two dimensions are the length of b and the length of a. The third dimension is the number of elements in each row of a plus 1. We can then use broadcasting to fill in this array.
x, y = a.shape
z, = b.shape
result = np.empty((z, x, y + 1))
result[...,:y] = a
result[...,y] = b[:,None]
At this point, to get the exact answer you asked for, you'll need to swap the first two axes, and then merge those two axes into a single axis.
result.swapaxes(0, 1).reshape(-1, y + 1)
An hour later. . . .
I realized by being a little bit more clever, I didn't need to swap axes. This also has the nice benefit that the result is a contiguous array.
def convert1d(a, b):
x, y = a.shape
z, = b.shape
result = np.empty((x, z, y + 1))
result[...,:y] = a[:,None,:]
result[...,y] = b
return result.reshape(-1, y + 1)
this is very "scotch tape" solution:
import numpy as np
a = np.array(
[
[1, 2],
[3, 4],
[5, 6]
]
)
b = np.array(
[7, 8, 9, 10]
)
z = []
for x in b:
for y in a:
z.append(np.append(y, x))
np.array(z).reshape(3, 4, 3)
You need to use np.c_ to attach to join two dataframe. I also used np.full to generate a column of second array (b). The result are like what follows:
result = [np.c_[a, np.full((a.shape[0],1), x)] for x in b]
result
Output
[array([[1, 2, 7],
[3, 4, 7],
[5, 6, 7]]),
array([[1, 2, 8],
[3, 4, 8],
[5, 6, 8]]),
array([[1, 2, 9],
[3, 4, 9],
[5, 6, 9]]),
array([[ 1, 2, 10],
[ 3, 4, 10],
[ 5, 6, 10]])]
The output might be kind of messy. But it's exactly like what you mentioned as your desired output. To make sure, you cun run below to see what comes from the first element in the result array:
print(result[0])
Output
array([[1, 2, 7],
[3, 4, 7],
[5, 6, 7]])

Perform operation in NumPy array except for some values

Is there a simple way to lock/freeze an element within a Numpy Array. I would like to do several operations over a Numpy Array in python while keeping some specific values as they are originally.
for example,
if a have a Numpy Array a ;
[[ 1 3 4 5],
[6 7 8 0],
[9 10 11 2]]
and another Numpy Array b ;
[[2 0 4 10],
[11 5 12 3],
[6 8 7 9]]
and c = a+b but keeping the original values of 3, 8 and 2 in a.
My arrays are quite big and I would like a solution where I don't have to use a for loop, an if statement or something similar.
You can use np.isin to build a mask, and then np.where to populate from either a or a+b depending on on the result:
m = np.isin(a, [3,8,2])
c = np.where(m, a, a+b)
Or as #hpaulj suggests, you could also use where and out in np.add, which would modify a in-place:
np.add(a, b, where=~np.isin(a,[3,8,2]), out=a)
array([[ 3, 3, 8, 15],
[17, 12, 8, 3],
[15, 18, 18, 2]])

Einsum multiply each row with every one

im trying to find a special Matrix multiplication fully vectorized(without loops). Basically im trying to multipy each row with every row. for examplea=np.array([[1,2],[3,4],[5,6]]) and b=np.array([[1,1],[2,2],[3,3]]) then the result should be([3,7,11],[6,14,22],[9,21,33]])
(first all rows of "a" are multiplied with the first row of b, which gives us (3,7,11) and then the next row of a with all rows of be..)
Here is a solution using np.einsum:
>>> import numpy as np
>>> a = np.array([[1,2],[3,4],[5,6]])
>>> b = np.array([[1,1],[2,2],[3,3]])
>>> np.einsum('kj,ij->ik', a, b)
array([[ 3, 7, 11],
[ 6, 14, 22],
[ 9, 21, 33]])
This is equivalent to b#a.T, or equivalently (a#b.T).T like the other answers have already pointed out.
you can use dot function in numpy.
a = [[1,0],[0,1]]
b = [[4,1],[2,2]]
AdotB = np.dot(a,b)
AdotB is equal to [[4, 1],[2, 2]]
but you should be careful because it will raise ValueError if the last dimension of a is not the same size as the second-to-last dimension of b.
The answer:
a=np.array([[1,2],[3,4],[5,6]])
b=np.array([[1,1],[2,2],[3,3]])
res = a.dot(b.T).T
print('a =\n', a, '\n')
print('b =\n', b, '\n')
print('result =', '\n', res)
The output:
a =
[[1 2]
[3 4]
[5 6]]
b =
[[1 1]
[2 2]
[3 3]]
result =
[[ 3 7 11]
[ 6 14 22]
[ 9 21 33]]

How to update all the values of a numpy array using values from another array

*Question edited/updated to add an example
Hi all! I have this a np.array. Based on the reference values of it, I want to update array b, which is my matrix. The "1st column" of a represents a code and the "2nd column" is my reference value. The matrix is populated with codes and I must replace them. See below the example.
import numpy as np
a = np.asarray([[0, 11], [1, 22], [2, 33]])
b = np.asarray([[0, 14, 12, 2], [1, 1, 7, 0], [0, 0,3,5], [1, 2, 2, 6]])
In other words: I want to replace the 0, 1, 2 values in "b" by 11, 22, 33, respectively.
Which is the best way to do that, considering that my real a array has +- 50 codes and my real b matrices have a shape of (850,850).
Thanks in advance!
If I understand the question correctly, this example should show what you're asking for?
Assuming a is the matrix as you've listed above, and b is the list you want to write to
import numpy as np
a = np.asarray([[0, 10], [2, 30], [1, 40]])
b = np.zeros(3)
b[a[:, 0]] = a[:, 1]
where the [:, 0] is the index to be changed, and [:, 1] is what to populate it with
If codes are not too long integers, You just have to build the correct lookup table :
lut = np.arange(b.max()+1)
k,v = a.T
lut[k] = v
For :
>>> b
[[ 0 14 12 2]
[ 1 1 7 0]
[ 0 0 3 5]
[ 1 2 2 6]]
>>> lut[b]
[[11 14 12 33]
[22 22 7 11]
[11 11 3 5]
[22 33 33 6]]
undefined codes are mapped to themselves,code=value.

Absolute difference of two NumPy arrays

Is there an efficient way/function to subtract one matrix from another and writing the absolute values in a new matrix?
I can do it entry by entry but for big matrices, this will be fairly slow...
For example:
X = [[12,7,3],
[4 ,5,6],
[7 ,8,9]]
Y = [[5,8,1],
[6,7,3],
[4,5,9]]
for i in range(len(r_0)):
for j in range(len(r)):
delta_r[i][j]= sqrt((r[i][j])**2 - (r_0[i][j])**2)
If you want the absolute element-wise difference between both matrices, you can easily subtract them with NumPy and use numpy.absolute on the resulting matrix.
import numpy as np
X = [[12,7,3],
[4 ,5,6],
[7 ,8,9]]
Y = [[5,8,1],
[6,7,3],
[4,5,9]]
result = np.absolute(np.array(X) - np.array(Y))
Outputs:
[[7 1 2]
[2 2 3]
[3 3 0]]
Alternatively (although unnecessary), if you were required to do so in native Python you could zip the dimensions together in a nested list comprehension.
result = [[abs(a-b) for a, b in zip(xrow, yrow)]
for xrow, yrow in zip(X,Y)]
Outputs:
[[7, 1, 2], [2, 2, 3], [3, 3, 0]]
Doing this becomes trivial if you cast your 2D arrays to numpy arrays:
import numpy as np
X = [[12, 7, 3],
[4, 5, 6],
[7, 8, 9]]
Y = [[5, 8, 1],
[6, 7, 3],
[4, 5, 9]]
X, Y = map(np.array, (X, Y))
result = X - Y
Numpy is designed to work easily and efficiently with matrices.
Also, you spoke about subtracting matrices, but you also seemed to want to square the individual elements and then take the square root on the result. This is also easy with numpy:
result = np.sqrt((A ** 2) - (B ** 2))
I recommend using NumPy
X = numpy.array([
[12,7,3],
[4 ,5,6],
[7 ,8,9]
])
Y = numpy.array([
[5,8,1],
[6,7,3],
[4,5,9]
])
delta_r = numpy.sqrt(X ** 2 - Y ** 2)

Categories

Resources