extracting a subarray from an array in python using numpy - python

if this is given on a homework assignment:
import numpy as np
room_matrix = \
np.array(
[[6, 3, 4, 1],
[5, 2, 3, 2],
[8, 3, 6, 2],
[5, 1, 3, 1],
[10, 4, 7, 2]])
and the task is:
write an expression that retrieves the following submatrix from room_matrix:
array([[2,3],
[3,6]])
I have done this so far:
a=room_matrix[1,1:3]
b=room_matrix[2,1:3]
then I print "a" and "b" and the output is:
[2 3]
[3 6]
but I want them to be executed as an actual subarray like so:
array([[2,3],
[3,6]])
Can I concatenate "a" and "b"? Or is there another way to extract a sub array so that the output actually shows it as an array, and not just me printing two splices? I hope this makes sense. Thank you.

You needn't do that in two lines. Numpy allows you to splice within a single statement, like this:
room_matrix[1:3, 1:3]
#will slice rows starting from 1 to 2 (row numbers start at 0), likewise for columns

How about this:
In [1]: import numpy as np
In [2]: room_matrix = \
...: np.array(
...: [[6, 3, 4, 1],
...: [5, 2, 3, 2],
...: [8, 3, 6, 2],
...: [5, 1, 3, 1],
...: [10, 4, 7, 2]])
In [3]: room_matrix
Out[3]:
array([[ 6, 3, 4, 1],
[ 5, 2, 3, 2],
[ 8, 3, 6, 2],
[ 5, 1, 3, 1],
[10, 4, 7, 2]])
In [4]: room_matrix[1:3, 1:3]
Out[4]:
array([[2, 3],
[3, 6]])

The question has already been answered, so just throwing it out there, but, indeed, you could use np.vstack to "concatenate" your a and b matrices to get the desired result:
In [1]: import numpy as np
In [2]: room_matrix = \
...: np.array(
...: [[6, 3, 4, 1],
...: [5, 2, 3, 2],
...: [8, 3, 6, 2],
...: [5, 1, 3, 1],
...: [10, 4, 7, 2]])
In [3]: a=room_matrix[1,1:3]
In [4]: b=room_matrix[2,1:3]
In [5]: np.vstack((a,b))
Out[5]:
array([[2, 3],
[3, 6]])

Related

Given indexes, get values from numpy matrix

Let's say I have this numpy matrix:
>>> mat = np.matrix([[3,4,5,2,1], [1,2,7,6,5], [8,9,4,5,2]])
>>> mat
matrix([[3, 4, 5, 2, 1],
[1, 2, 7, 6, 5],
[8, 9, 4, 5, 2]])
Now let's say I have some indexes in this form:
>>> ind = np.matrix([[0,2,3], [0,4,2], [3,1,2]])
>>> ind
matrix([[0, 2, 3],
[0, 4, 2],
[3, 1, 2]])
What I would like to do is to get three values from each row of the matrix, specifically values at columns 0, 2, and 3 for the first row, values at columns 0, 4 and 2 for the second row, etc. This is the expected output:
matrix([[3, 5, 2],
[1, 5, 7],
[5, 9, 4]])
I've tried using np.take but it doesn't seem to work. Any suggestion?
This is take_along_axis.
>>> np.take_along_axis(mat, ind, axis=1)
matrix([[3, 5, 2],
[1, 5, 7],
[5, 9, 4]])
This will do it: mat[np.arange(3).reshape(-1, 1), ind]
In [245]: mat[np.arange(3).reshape(-1, 1), ind]
Out[245]:
matrix([[3, 5, 2],
[1, 5, 7],
[5, 9, 4]])
(but take_along_axis in #user3483203's answer is simpler).

How to compute the dot product of every row of two different matrices fast using numpy in Python

Suppose I have two matrices and I want to take the row of the first matrix, transpose it and apply # to the corresponding row of the second matrix to obtain a matrix. Do that for the number of rows in each. For example:
Matrix A = N x p
Matrix B = N x q
After operation I have N (p x q) matrices
An example to illustrate for the first row.
>>> x
array([[2, 1, 2],
[4, 3, 1],
[1, 2, 3],
[1, 2, 1]])
>>> g
array([[2, 3],
[3, 3],
[1, 2],
[2, 5]])
After first operation:
>>> x[0,:,np.newaxis] # g[np.newaxis,0,:]
array([[4, 6],
[2, 3],
[4, 6]])
After second operation:
>>> x[1,:,np.newaxis] # g[np.newaxis,1,:]
array([[12, 12],
[ 9, 9],
[ 3, 3]])
And so on, N times such that it would return N (p x q) matrices (Here 3 (3x2) matrices). How can this be done in Numpy with no loop?
In [17]: x = np.array([[2, 1, 2],
...: [4, 3, 1],
...: [1, 2, 3],
...: [1, 2, 1]])
...: g = np.array([[2, 3],
...: [3, 3],
...: [1, 2],
...: [2, 5]])
In [18]: x.shape
Out[18]: (4, 3)
In [19]: g.shape
Out[19]: (4, 2)
With broadcasting, multiply a (4,3,1) with a (4,1,2) to produce (4,3,2):
In [20]: x[:,:,None]*g[:,None,:]
Out[20]:
array([[[ 4, 6],
[ 2, 3],
[ 4, 6]],
[[12, 12],
[ 9, 9],
[ 3, 3]],
[[ 1, 2],
[ 2, 4],
[ 3, 6]],
[[ 2, 5],
[ 4, 10],
[ 2, 5]]])
In [21]: _.shape
Out[21]: (4, 3, 2)
x[:,:,None]#g[:,None,:] does the same thing, doing sum-of-products on the shared size 1 dimension.
You can try this:
np.split(np.repeat(x.T, g.shape[1], axis=1) * g.ravel(), g.shape[0], axis=1)
It gives:
[array([[4, 6],
[2, 3],
[4, 6]]),
array([[12, 12],
[ 9, 9],
[ 3, 3]]),
array([[1, 2],
[2, 4],
[3, 6]]),
array([[ 2, 5],
[ 4, 10],
[ 2, 5]])]

Subsampling 3D array using the neighbourhood sum

The title is probably confusing. I have a reasonably large 3D numpy array. I'd like to cut it's size by 2^3 by binning blocks of size (2,2,2). Each element in the new 3D array should then contain the sum of the elements in it's respective block in the original array.
As an example, consider a 4x4x4 array:
input = [[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]],
[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]],
... ]]]
(I'm only representing half of it to save space). Notice that all the elements with the same value constitute a (2x2x2) block. The output should be a 2x2x2 array such that each element is the sum of a block:
output = [[[8, 16],
[24, 32]],
... ]]]
So 8 is the sum of all 1's, 16 is the sum of the 2's, and so on.
There's a builtin to do those block-wise reductions - skimage.measure.block_reduce-
In [36]: a
Out[36]:
array([[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]],
[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]]])
In [37]: from skimage.measure import block_reduce
In [39]: block_reduce(a, block_size=(2,2,2), func=np.sum)
Out[39]:
array([[[ 8, 16],
[24, 32]]])
Use other reduction ufuncs, say max-reduction -
In [40]: block_reduce(a, block_size=(2,2,2), func=np.max)
Out[40]:
array([[[1, 2],
[3, 4]]])
Implementing such a function isn't that difficult with NumPy tools and could be done like so -
def block_reduce_numpy(a, block_size, func):
shp = a.shape
new_shp = np.hstack([(i//j,j) for (i,j) in zip(shp,block_size)])
select_axes = tuple(np.arange(a.ndim)*2+1)
return func(a.reshape(new_shp),axis=select_axes)

Dot product columns by rows python - numpy

I am trying to take out the dot product of each row against itself in a nx3 vector. Let me explain a little better: what I need is to go from a nx3 to a nx3x3 array.
If i have the following:
A = np.array([[1, 2, 2],
[4, 2, 3])
I would like to get what it would be:
First element:
np.dot(A[0].reshape(3,1), A[0].reshape(1,3)) = array([[1, 2, 2], [2, 4, 4], [2, 4, 4]])
Second element:
np.dot(A[1].reshape(3,1), A[1].reshape(1,3)) = array([[16, 8, 12], [8, 4, 6], [12, 6, 9]])
So my final array would be:
result = array([[[ 1, 2, 2],
[ 2, 4, 4],
[ 2, 4, 4]],
[[16, 8, 12],
[ 8, 4, 6],
[12, 6, 9]])
result.shape = (2, 3, 3)
I know I can do this with a for loop but I guess there must be a way to do it faster and more directly. Speed is vital for what I need.
Hope I explained myself correctly enough. Thank you in advance.
In [301]: A = np.array([[1, 2, 2],
...: [4, 2, 3]])
...:
...:
This isn't a dot product; there's no summing of products. Rather it's more like an outer product, increasing the number of dimensions. numpy with broadcasting does this nicely:
In [302]: A[:,:,None]*A[:,None,:]
Out[302]:
array([[[ 1, 2, 2],
[ 2, 4, 4],
[ 2, 4, 4]],
[[16, 8, 12],
[ 8, 4, 6],
[12, 6, 9]]])

list as columns in python

I have a list for example:
x = [1,2,3,4,5]
and I want to convert it into a matrix that looks like so:
mat = [ 1 1 1
2 2 2
3 3 3
4 4 4
5 5 5 ]
so each column in the matrix is the list.
is there an easy way doing so with numpy or just regular python?
thank you
Maybe you need to repeat i.e
n = 3 # No of repetition
np.repeat(np.array(x),n).reshape(-1,n)
array([[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]])
without any modules
a = [1, 2, 3, 4, 5]
n = 3
b = [[x] * n for x in a]
print(b)
Let's use np.tile:
import numpy as np
arr = np.array(x)
np.tile(arr,3).reshape(5,3, order='F')
Output:
array([[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]])
Another array option:
In [248]: np.stack([a]*3,axis=1)
Out[248]:
array([[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]])
You need to be careful with list replication:
In [250]: b=[a]*3
In [251]: b[0][0]=30
In [252]: b
Out[252]: [[30, 2, 3, 4, 5], [30, 2, 3, 4, 5], [30, 2, 3, 4, 5]]
# a is also changed
It replicates the pointer, not the values. The array stack makes a copy.
np.array will join those lists along a new first axis. stack does something similar (but using np.concatenate), and allows us to join them on a new 2nd axis.
In [255]: np.array(b)
Out[255]:
array([[30, 2, 3, 4, 5],
[30, 2, 3, 4, 5],
[30, 2, 3, 4, 5]])

Categories