Add a matrix outside a loop - python

I have a function that gives me a matrix of 17*3 (float (17,3)). I call that function again and again in a loop, i want to add the matrices so that rows remain 17 but column keeps on adding to make one big matrix.

Without NUMPY:
Transpose the matrix first because you are not gonna touch the 17 rows.
# a matrix is 17 * 3
a_transpose = [[a[j][i] for j in range(len(a))] for i in range(len(a[0]))]
Then, add the column of 17 rows as one row of 17 columns
a_transpose.append([1,2,3, ... 17])
Once, you are done adding several rows, transpose the matrix back as said above. That way, you don't iterate through your array 17 times everytime you add a column to your matrix.
With NUMPY:
Transpose
# a matrix is 17 * 3
a = numpy.array(a)
a_transpose = a.transpose()
Add a row (17 column values you wanted to add)
a_transpose.append([1,2,3, .... 17], axis=0)

Your function:
In [187]: def foo(i):
...: return np.arange(i,i+6).reshape(3,2)
...:
Iteratively build a list of arrays:
In [188]: alist = []
In [189]: for i in range(4):
...: alist.append(foo(i))
...:
In [190]: alist
Out[190]:
[array([[0, 1],
[2, 3],
[4, 5]]), array([[1, 2],
[3, 4],
[5, 6]]), array([[2, 3],
[4, 5],
[6, 7]]), array([[3, 4],
[5, 6],
[7, 8]])]
Make an array from that list:
In [191]: np.concatenate(alist, axis=1)
Out[191]:
array([[0, 1, 1, 2, 2, 3, 3, 4],
[2, 3, 3, 4, 4, 5, 5, 6],
[4, 5, 5, 6, 6, 7, 7, 8]])

Related

How to loop back to beginning of the array for out of bounds index in numpy?

I have a 2D numpy array that I want to extract a submatrix from.
I get the submatrix by slicing the array as below.
Here I want a 3*3 submatrix around an item at the index of (2,3).
>>> import numpy as np
>>> a = np.array([[0, 1, 2, 3],
... [4, 5, 6, 7],
... [8, 9, 0, 1],
... [2, 3, 4, 5]])
>>> a[1:4, 2:5]
array([[6, 7],
[0, 1],
[4, 5]])
But what I want is that for indexes that are out of range, it goes back to the beginning of array and continues from there. This is the result I want:
array([[6, 7, 4],
[0, 1, 8],
[4, 5, 2]])
I know that I can do things like getting mod of the index to the width of the array; but I'm looking for a numpy function that does that.
And also for an one dimensional array this will cause an index out of range error, which is not really useful...
This is one way using np.pad with wraparound mode.
>>> a = np.array([[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 0, 1],
[2, 3, 4, 5]])
>>> pad_width = 1
>>> i, j = 2, 3
>>> startrow, endrow = i-1+pad_width, i+2+pad_width # for 3 x 3 submatrix
>>> startcol, endcol = j-1+pad_width, j+2+pad_width
>>> np.pad(a, (pad_width, pad_width), 'wrap')[startrow:endrow, startcol:endcol]
array([[6, 7, 4],
[0, 1, 8],
[4, 5, 2]])
Depending on the shape of your patch (eg. 5 x 5 instead of 3 x 3) you can increase the pad_width and start and end row and column indices accordingly.
np.take does have a mode parameter which can wrap-around out of bound indices. But it's a bit hacky to use np.take for multidimensional arrays since the axis must be a scalar.
However, In your particular case you could do this:
a = np.array([[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 0, 1],
[2, 3, 4, 5]])
np.take(a, np.r_[2:5], axis=1, mode='wrap')[1:4]
Output:
array([[6, 7, 4],
[0, 1, 8],
[4, 5, 2]])
EDIT
This function might be what you are looking for (?)
def select3x3(a, idx):
x,y = idx
return np.take(np.take(a, np.r_[x-1:x+2], axis=0, mode='wrap'), np.r_[y-1:y+2], axis=1, mode='wrap')
But in retrospect, i recommend using modulo and fancy indexing for this kind of operation (it's basically what the mode='wrap' is doing internally anyways):
def select3x3(a, idx):
x,y = idx
return a[np.r_[x-1:x+2][:,None] % a.shape[0], np.r_[y-1:y+2][None,:] % a.shape[1]]
The above solution is also generalized for any 2d shape on a.

Find row indices from two 2d arrays with close values

I have an array a
a = np.array([[4, 4],
[5, 4],
[6, 4],
[4, 5],
[5, 5],
[6, 5],
[4, 6],
[5, 6],
[6, 6]])
and an array b
b = np.array([[4.001,4],
[8.001,4],
[5,4.0003],
[5.9999,5]])
I want to find the indices of a that have values very close to those of b. If the b array has the exact same values as the values in a I can use the following code.
np.where((a==b[:,None]).all(-1))[1]
For clarity; I would like the code to return the following: [0,1,5]
These are the indices of a that are very close to the rows in b. The value in b with the value[8.001,4] is discarded as it is not in a.
I think combining the code above with np.allclose() would fix it, however I can't seem to figure out how to do this, can you help me?
Instead of ==, use np.linalg.norm on a - b[:, np.newaxis] to get the distance of each row in a to each row in b.
If a and b have many rows, this will use lots of memory: e.g., if each has 10,000 rows, the vecdiff array below would be 10,000-by-10,000, or 100,000,000 elements; using doubles this is 800MB.
In [50]: a = np.array([[4, 4],
...: [5, 4],
...: [6, 4],
...: [4, 5],
...: [5, 5],
...: [6, 5],
...: [4, 6],
...: [5, 6],
...: [6, 6]])
...:
In [51]: b = np.array([[4.001,4],
...: [8.001,4],
...: [5,4.0003],
...: [5.9999,5]])
In [52]: vecdist = np.linalg.norm(a - b[:, np.newaxis], axis=-1)
In [53]: closeidx = np.flatnonzero(vecdist.min(axis=0) < 1e-2)
In [54]: print(closeidx)
[0 1 5]

Put numpy arrays split with np.split() back together

I have split a numpy array like so:
x = np.random.randn(10,3)
x_split = np.split(x,5)
which splits x equally into five numpy arrays each with shape (2,3) and puts them in a list. What is the best way to combine a subset of these back together (e.g. x_split[:k] and x_split[k+1:]) so that the resulting shape is similar to the original x i.e. (something,3)?
I found that for k > 0 this is possible with you do:
np.vstack((np.vstack(x_split[:k]),np.vstack(x_split[k+1:])))
but this does not work when k = 0 as x_split[:0] = [] so there must be a better and cleaner way. The error message I get when k = 0 is:
ValueError: need at least one array to concatenate
The comment by Paul Panzer is right on target, but since NumPy now gently discourages vstack, here is the concatenate version:
x = np.random.randn(10, 3)
x_split = np.split(x, 5, axis=0)
k = 0
np.concatenate(x_split[:k] + x_split[k+1:], axis=0)
Note the explicit axis argument passed both times (it has to be the same); this makes it easy to adapt the code to work for other axes if needed. E.g.,
x_split = np.split(x, 3, axis=1)
k = 0
np.concatenate(x_split[:k] + x_split[k+1:], axis=1)
np.r_ can turn several slices into a list of indices.
In [20]: np.r_[0:3, 4:5]
Out[20]: array([0, 1, 2, 4])
In [21]: np.vstack([xsp[i] for i in _])
Out[21]:
array([[9, 7, 5],
[6, 4, 3],
[9, 8, 0],
[1, 2, 2],
[3, 3, 0],
[8, 1, 4],
[2, 2, 5],
[4, 4, 5]])
In [22]: np.r_[0:0, 1:5]
Out[22]: array([1, 2, 3, 4])
In [23]: np.vstack([xsp[i] for i in _])
Out[23]:
array([[9, 8, 0],
[1, 2, 2],
[3, 3, 0],
[8, 1, 4],
[3, 2, 0],
[0, 3, 8],
[2, 2, 5],
[4, 4, 5]])
Internally np.r_ has a lot of ifs and loops to handle the slices and their boundaries, but it hides it all from us.
If the xsp (your x_split) was an array, we could do xsp[np.r_[...]], but since it is a list we have to iterate. Well we could also hide that iteration with an operator.itemgetter object.
In [26]: operator.itemgetter(*Out[22])
Out[26]: operator.itemgetter(1, 2, 3, 4)
In [27]: np.vstack(operator.itemgetter(*Out[22])(xsp))

subtracting a certain row in a matrix

So I have a 4 by 4 matrix. [[1,2,3,4],[2,3,4,5],[3,4,5,6],[4,5,6,7]]
I need to subtract the second row by [1,2,3,4]
no numpy if possible. I'm a beginner and don't know how to use that
thnx
With regular Python loops:
a = [[1,2,3,4],[2,3,4,5],[3,4,5,6],[4,5,6,7]]
b = [1,2,3,4]
for i in range(4):
a[1][i] -= b[i]
Simply loop over the entries in the b list and subtract from the corresponding entries in a[1], the second list (ie row) of the a matrix.
However, NumPy can do this for you faster and easier and isn't too hard to learn:
In [47]: import numpy as np
In [48]: a = np.array([[1,2,3,4],[2,3,4,5],[3,4,5,6],[4,5,6,7]])
In [49]: a
Out[49]:
array([[1, 2, 3, 4],
[2, 3, 4, 5],
[3, 4, 5, 6],
[4, 5, 6, 7]])
In [50]: a[1] -= [1,2,3,4]
In [51]: a
Out[51]:
array([[1, 2, 3, 4],
[1, 1, 1, 1],
[3, 4, 5, 6],
[4, 5, 6, 7]])
Note that NumPy vectorizes many of its operations (such as subtraction), so the loops involved are handled for you (in fast, pre-compiled C-code).

Modify a particular row/column of a NumPy array

How do I modify particular a row or column of a NumPy array?
For example I have a NumPy array as follows:
P = array([[1, 2, 3],
[4, 5, 6]])
How do I change the elements of first row, [1, 2, 3], to [7, 8, 9] so that the P will become:
P = array([[7, 8, 9],
[4, 5, 6]])
Similarly, how do I change second column values, [2, 5], to [7, 8]?
P = array([[1, 7, 3],
[4, 8, 6]])
Rows and columns of NumPy arrays can be selected or modified using the square-bracket indexing notation in Python.
To select a row in a 2D array, use P[i]. For example, P[0] will return the first row of P.
To select a column, use P[:, i]. The : essentially means "select all rows". For example, P[:, 1] will select all rows from the second column of P.
If you want to change the values of a row or column of an array, you can assign it to a new list (or array) of values of the same length.
To change the values in the first row, write:
>>> P[0] = [7, 8, 9]
>>> P
array([[7, 8, 9],
[4, 5, 6]])
To change the values in the second column, write:
>>> P[:, 1] = [7, 8]
>>> P
array([[1, 7, 3],
[4, 8, 6]])
In a similar way if you want to select only two last columns for example but all rows you can use:
print P[:,1:3]
If you have lots of elements in a column:
import numpy as np
np_mat = np.array([[1, 2, 2],
[3, 4, 5],
[5, 6, 5]])
np_mat[:,2] = np_mat[:,2] * 3
print(np_mat)
It is making a multiplied by 3 change in third column:
[[ 1 2 6]
[ 3 4 15]
[ 5 6 15]]

Categories