How to insert one ndarray to another ndarray? - python

These are two ndarray.
A=[[1,2,3],[4,5,6],[7,8,9]]
B=[[31,42,53],[11,17,29],[100,59,32]]
How to make a new ndarray 'C' by merge two ndarray A and B?
C=[[1,2,3],[31,42,53],[4,5,6], [11,17,29],[7,8,9],[100,59,32]]

Using array-initialization to achieve that interweaving task -
def interweave(a, b):
N = a.shape[1]
M = a.shape[0] + b.shape[0]
out_dtype = np.result_type(a.dtype, b.dtype)
out = np.empty((M,N),dtype=out_dtype)
out[::2] = a
out[1::2] = b
return out
Sample run -
In [274]: A
Out[274]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [275]: B
Out[275]:
array([[ 31, 42, 53],
[ 11, 17, 29],
[100, 59, 32]])
In [276]: interweave(A, B)
Out[276]:
array([[ 1, 2, 3],
[ 31, 42, 53],
[ 4, 5, 6],
[ 11, 17, 29],
[ 7, 8, 9],
[100, 59, 32]])
If A and B are of same shapes, we can also stack and reshape -
In [283]: np.hstack((A,B)).reshape(-1,A.shape[1])
Out[283]:
array([[ 1, 2, 3],
[ 31, 42, 53],
[ 4, 5, 6],
[ 11, 17, 29],
[ 7, 8, 9],
[100, 59, 32]])
Or np.stack((A,B),axis=1).reshape(-1,A.shape[1]).

you can use numpy library. like this:
import numpy as np
A=[[1,2,3],[4,5,6],[7,8,9]]
B=[[31,42,53],[11,17,29],[100,59,32]]
C= np.concatenate((A, B), axis=0)
more information about concatenate with numpy in this link :
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.concatenate.html

Related

Python numpy function for matrix math

I have to np arrays
a = np.array[[1,2]
[2,3]
[3,4]
[5,6]]
b = np.array [[2,4]
[6,8]
[10,11]
I want to multiple each row of a against each element in array b so that array c is created with dimensions of a-rows x b rows (as columns)
c = np.array[[2,8],[6,16],[10,22]
[4,12],[12,21],[20,33]
....]
There are other options for doing this, but I would really like to leverage the speed of numpy's ufuncs...if possible.
any and all help is appreciated.
Does this do what you want?
>>> a
array([[1, 2],
[2, 3],
[3, 4],
[5, 6]])
>>> b
array([[ 2, 4],
[ 6, 8],
[10, 11]])
>>> a[:,None,:]*b
array([[[ 2, 8],
[ 6, 16],
[10, 22]],
[[ 4, 12],
[12, 24],
[20, 33]],
[[ 6, 16],
[18, 32],
[30, 44]],
[[10, 24],
[30, 48],
[50, 66]]])
>>> _.shape
(4, 3, 2)
Or if that doesn't have the right shape, you can reshape it:
>>> (a[:,None,:]*b).reshape((a.shape[0]*b.shape[0], 2))
array([[ 2, 8],
[ 6, 16],
[10, 22],
[ 4, 12],
[12, 24],
[20, 33],
[ 6, 16],
[18, 32],
[30, 44],
[10, 24],
[30, 48],
[50, 66]])

How to slice multidimensional array with Numpy, multiple columns?

I am generating multidimensional array of different sizes, though they'll all have an even number of columns.
>> import numpy as np
>> x = np.arange(24).reshape((3,8))
Which results in:
array([[ 0, 1, 2, 3, 4, 5, 6, 7],
[ 8, 9, 10, 11, 12, 13, 14, 15],
[16, 17, 18, 19, 20, 21, 22, 23]])
I am able to slice with numpy and get the first column in an array:
>> newarr = x[0:,0:2]
array([[ 0, 1],
[ 8, 9],
[16, 17]])
However, I want to have one array that is just a list of the columns where column 1 and 2 are together, 3 and 4 are together, and so on.. For example:
array([[[ 0, 1],
[ 8, 9],
[16, 17]],
[[ 2, 3],
[10, 11],
[18, 19]],
etc....]
)
This code below works but it's clunky and my arrays are not all the same. Some arrays have 16 columns, some have 34, some have 50, etc.
>> newarr = [x[0:,0:2]]+[x[0:,2:4]]+[x[0:,4:6]]
[array([[ 0, 1],
[ 8, 9],
[16, 17]]), array([[ 2, 3],
[10, 11],
[18, 19]])]
There's got to be a better way to do this than
newarr = [x[0:,0:2]]+[x[0:,2:4]]+[x[0:,4:6]]+...+[x[0:,n:n+2]]
Help!
My idea is adding a for loop:
slice_len = 2
x_list = [x[0:, slice_len*i:slice_len*(i+1)] for i in range(x.shape[1] // slice_len)]
Output:
[array([[ 0, 1],
[ 8, 9],
[16, 17]]), array([[ 2, 3],
[10, 11],
[18, 19]]), array([[ 4, 5],
[12, 13],
[20, 21]]), array([[ 6, 7],
[14, 15],
[22, 23]])]

Numpy dot() function equivalent

This question is just out of pure curiosity. Suppose I have 2 matrices a and b.
a=np.array([[1, 2],
[2, 3],
[4, 5]])
b=np.array([[1, 2, 3, 4],
[2, 3, 4, 5]])
To find their dot product, I might use np.dot(a,b). But is there any other way to do this? I am not asking for any other alias functions. But maybe another way to do this like np.sum(a*b, axis=1) (I know that doesn't work, it is just an example). And what if I have a 3-D matrix? Is there any other way to compute their dot product as well (without using any functions)?
Thanks in advance!
In [66]: a=np.array([[1, 2],
...: [2, 3],
...: [4, 5]])
...:
...: b=np.array([[1, 2, 3, 4],
...: [2, 3, 4, 5]])
...:
...:
In [67]: np.dot(a,b)
Out[67]:
array([[ 5, 8, 11, 14],
[ 8, 13, 18, 23],
[14, 23, 32, 41]])
In [68]: a#b
Out[68]:
array([[ 5, 8, 11, 14],
[ 8, 13, 18, 23],
[14, 23, 32, 41]])
In [69]: np.einsum('ij,jk',a,b)
Out[69]:
array([[ 5, 8, 11, 14],
[ 8, 13, 18, 23],
[14, 23, 32, 41]])
Broadcasted multiply and sum:
In [71]: (a[:,:,None]*b[None,:,:]).sum(axis=1)
Out[71]:
array([[ 5, 8, 11, 14],
[ 8, 13, 18, 23],
[14, 23, 32, 41]])
In [72]: (a[:,:,None]*b[None,:,:]).shape
Out[72]: (3, 2, 4)

vectorizations of matrix multiplication

I have many 3*2 matrices(A1,A2,A3..), and each of the 3*2 is a draw. In the case two draws, we have a 3*4 ( we horizontally stack each draw of A1,A2). Clearly, it is easier for me to draw the 3*4 matrix (A) as a larger matrices once instead of draw a 3*2 over and over again.
But I need to perform a matrix multiplication for each draw(each A1,A2...) to a matrix B. Say A1*B, and A2*B ...AN*B
#each draw of the 3*2 matrix
A1 = np.array([[ 0, 1],
[ 4, 5],
[ 8, 9]])
A2 = np.array([[ 2, 3],
[ 6, 7],
[ 10, 11]])
# A is [A1,A2]
# Easier to draw A once for all (the larger matrix)
A = np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
b = np.array([[ 0, 1],
[ 4, 5]
])
desired output
array([[ 4, 5, 12, 17],
[20, 29, 28, 41],
[36, 53, 44, 65]])
You can reshape matrix A to 2 columns so that it is conformable to b, do the matrix multiplication, and then reshape it back:
np.dot(A.reshape(-1, 2), b).reshape(3, -1)
#array([[ 4, 5, 12, 17],
# [20, 29, 28, 41],
# [36, 53, 44, 65]])
If you are unsure about how to store/stack the incoming arrays, one way would be stacking those as a 3D array, such that the each of those incoming arrays are index-able by its first axis -
a = np.array((A1,A2))
Sample run -
In [143]: a = np.array((A1,A2))
In [144]: a.shape
Out[144]: (2, 3, 2)
|-----------------> axis of stacking
Then, to get the equivalent output of matrix-multiplications of each incoming array with b, we could use np.tensordot on the 3D stacked array a with b, thus losing the last axis from a and first from b in the sum-reduction, like so -
out = np.tensordot(a,b,axes=((2),(0)))
Let's have a look at the output values and compare against each matrix-multiplication with A1, A2, etc. -
In [138]: out[0]
Out[138]:
array([[ 4, 5],
[20, 29],
[36, 53]])
In [139]: out[1]
Out[139]:
array([[12, 17],
[28, 41],
[44, 65]])
In [140]: A1.dot(b)
Out[140]:
array([[ 4, 5],
[20, 29],
[36, 53]])
In [141]: A2.dot(b)
Out[141]:
array([[12, 17],
[28, 41],
[44, 65]])
Thus, essentially with this stacking operation and later on tensordot we have :
out[0], out[1], .... = A1.dot(b), A2.dot(b), ....
Alternative to np.tensordot -
We could use a simpler version with np.matmul, to get the same output as with tensordot -
out = np.matmul(a,b)
On Python 3.5, there's an even simpler version that replaces np.matmul, the # operator -
out = a # b
Even if not needed for the calculation einsum can help us think through the problem:
In [584]: np.einsum('ij,jk->ik', A1,b)
Out[584]:
array([[ 4, 5],
[20, 29],
[36, 53]])
In [585]: np.einsum('ij,jk->ik', A2,b)
Out[585]:
array([[12, 17],
[28, 41],
[44, 65]])
A is (3,4), which won't work with the (2,2) b. Think of it as trying work with a doubled j dimension: 'i(2j),jk->i?k'. But what if we inserted an axis? 'imk,jk->imk'? Or added the extra dimension to i?
In [587]: np.einsum('imj,jk->imk', A.reshape(3,2,2),b)
Out[587]:
array([[[ 4, 5],
[12, 17]],
[[20, 29],
[28, 41]],
[[36, 53],
[44, 65]]])
The numbers are there, just the shape is (3,2,2).
In [590]: np.einsum('imj,jk->imk', A.reshape(3,2,2),b).reshape(3,4)
Out[590]:
array([[ 4, 5, 12, 17],
[20, 29, 28, 41],
[36, 53, 44, 65]])
Or you could build A from the start so that mij,jk->mik works (#Divaker)
#Psidom:
np.einsum('ij,jk->ik', A.reshape(3,2,2).reshape(-1,2) ,b).reshape(3,-1)
`#piRSquared':
'kj,jI->kI`
Shift you perspective. You are locking yourself into 3 x 2 unnecessarily.
You can think of A1 and A2 as 2x3 instead, then A would be
array([[ 0, 4, 8, 2, 6, 10],
[ 1, 5, 9, 3, 7, 11]])
Then take the transpose of b = b.T
array([[0, 4],
[1, 5]])
So that you can do you operation
b # A
array([[ 4, 20, 36, 12, 28, 44],
[ 5, 29, 53, 17, 41, 65]])
Let your "draws" look like this
A = np.random.randint(10, size=(2, 9))
A
array([[7, 2, 1, 0, 9, 9, 1, 0, 2],
[8, 6, 1, 6, 6, 2, 4, 2, 9]])
b # A
array([[32, 24, 4, 24, 24, 8, 16, 8, 36],
[47, 32, 6, 30, 39, 19, 21, 10, 47]])
​

Multiplying 2d array by 1d array

I have an 2D-array a with shape (k,n) and I want to 'multiply' it with an 1D-array b of shape (m,):
a = np.array([[2, 8],
[4, 7],
[1, 2],
[5, 2],
[7, 4]])
b = np.array([3, 5, 5])
As a result of the 'multiplication' I'm looking for:
array([[[2*3,2*5,2*5],[8*3,8*5,8*5]],
[[4*3,4*5,4*5],[7*3,7*5,7*5]],
[[1*3,1*5,1*5], ..... ]],
................. ]]])
= array([[[ 6, 10, 10],
[24, 40, 40]],
[[12, 20, 20],
[21, 35, 35]],
[[ 3, 5, 5],
[ ........ ]],
....... ]]])
I could solve it with a loop of course, but I'm looking for a fast vectorized way of doing it.
Extend a to a 3D array case by adding a new axis at the end with np.newaxis/None and then do elementwise multiplication with b, bringing in broadcasting for a vectorized solution, like so -
b*a[...,None]
Sample run -
In [19]: a
Out[19]:
array([[2, 8],
[4, 7],
[1, 2],
[5, 2],
[7, 4]])
In [20]: b
Out[20]: array([3, 5, 5])
In [21]: b*a[...,None]
Out[21]:
array([[[ 6, 10, 10],
[24, 40, 40]],
[[12, 20, 20],
[21, 35, 35]],
[[ 3, 5, 5],
[ 6, 10, 10]],
[[15, 25, 25],
[ 6, 10, 10]],
[[21, 35, 35],
[12, 20, 20]]])

Categories

Resources