How do you index a numpy array that wraps around when its out of bounds?
For example, I have 3x3 array:
import numpy as np
matrix = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]])
##
[[ 1 2 3 4 5]
[ 6 7 8 9 10]
[11 12 13 14 15]]
Say I would like to index the values around index (2,4) where value 15 is located. I would like to get back the array with values:
[[9, 10, 6]
[14, 15, 11]
[4, 5, 1]]
Basically all the values around 15 was returned, assuming it wraps around
A fairly standard idiom to find the neighboring elements in a numpy array is arr[x-1:x+2, y-1:y+2]. However, since you want to wrap, you can pad your array using wrap mode, and offset your x and y coordinates to account for this padding.
This answer assumes that you want the neighbors of the first occurence of your desired element.
First, find the indices of your element, and offset to account for padding:
x, y = np.unravel_index((m==15).argmax(), m.shape)
x += 1; y += 1
Now pad, and index your array to get your neighbors:
t = np.pad(m, 1, mode='wrap')
out = t[x-1:x+2, y-1:y+2]
array([[ 9, 10, 6],
[14, 15, 11],
[ 4, 5, 1]])
Here's how you can do it without padding. This can generalize easily to when you want more than just one neighbor and without the overhead of padding the array.
def get_wrapped(matrix, i, j):
m, n = matrix.shape
rows = [(i-1) % m, i, (i+1) % m]
cols = [(j-1) % n, j, (j+1) % n]
return matrix[rows][:, cols]
res = get_wrapped(matrix, 2, 4)
Let me explain what's happening here return matrix[rows][:, cols]. This is really two operations.
The first is matrix[rows] which is short hand for matrix[rows, :] which means give me the selected rows, and all columns for those rows.
Then next we do [:, cols] which means give me all the rows and the selected cols.
The take function works in-place.
>>> a = np.arange(1, 16).reshape(3,5)
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]])
>>> b = np.take(a, [3,4,5], axis=1, mode='wrap')
array([[ 4, 5, 1],
[ 9, 10, 6],
[14, 15, 11]])
>>> np.take(b, [1,2,3], mode='wrap', axis=0)
array([[ 9, 10, 6],
[14, 15, 11],
[ 4, 5, 1]])
Related
The input array is x with dimensions (1 x 3) and the output array is 3 x 3 (column of input x column of input). The output array's diagonals are the values^2. If row != column, then the formula is x(row)+x(col) for each value. Currently for 1 x 3 but should assume a variety of dimensions as input. Cannot use 'def'. The current code does not work, what would you recommend?
x = np.array([[0, 5, 10]])
output array formulas =
[[i^2, x(row)+x(col), x(row)+x(col)]
[x(row)+x(col), i^2, x(row)+x(col)]
[x(row)+x(col), x(row)+x(col), i^2]]
# where row and column refer to the output matrix row, column. For example, the value in (1,2) is x(1)+x(2)= 5
ideal output =
[[0 5 10]
[5 25 15]
[10 15 100]]
Code Attempted:
x = np.array([[0, 5, 10]])
r, c = np.shape(x)
results = np.zeros((c, c))
g[range(c), range(c)] = x**2
for i in x:
for j in i:
results[i,j] = x[i]+x[j]
Learn to use numpy methods and broadcasting:
>>> x
array([[ 0, 5, 10]])
>>> x.T
array([[ 0],
[ 5],
[10]])
>>> x.T + x
array([[ 0, 5, 10],
[ 5, 10, 15],
[10, 15, 20]])
>>> result = x.T + x
>>> result
array([[ 0, 5, 10],
[ 5, 10, 15],
[10, 15, 20]])
Then this handy built-in:
>>> np.fill_diagonal(result, x**2)
>>> result
array([[ 0, 5, 10],
[ 5, 25, 15],
[ 10, 15, 100]])
Can replace the results[range(c), range(c)] = x**2
Try this:
x.repeat(x.shape[1], axis=0)
x = x+x.T
x[np.arange(len(x)),np.arange(len(x))] = (np.diag(x)/2)**2
I have a problem, which seems to be easy but it is causing me a lot of headache.
The problem is that I'm programming in python (I'm relative new to it) and I'm looking for an aquivalent of the function max (min) of a matrix in matlab but using numpy.
What I want to do is to get the minimum value and its index in a matrix
Just to keep it as easiest as possible with an example, let's say this is the matrix:
arr2D = np.array([[11, 12, 13, 34],
[14, 15, 16, 3],
[17, 15, 11, 1],
[7, 5, 11, 4],
[1, 12, 4, 4],
[12, 14, 15,-3]])
in matlab I would do:
[local_max, index] = min(arr2D)
and I would get the min value and its index for every column in the matrix.
Trying to repeat the same in python (after looking here and here) with the following code:
print(np.where(arr2D == np.amin(arr2D, axis = 0))) # axis 0 is for columns
I get the following output:
(array([3, 4, 4, 5]), array([1, 0, 2, 3]))
which is not really what I want to get!
The expected output should be:
[1, 4] # Meaning the minimum value is 1 and it is in row 4 for the first column
[5, 3] # Meaning the minimum value is 5 and it is in row 3 for the second column
[4, 4] # Meaning the minimum value is 4 and it is in row 4 for the third column
[-3, 5] # Meaning the minimum value is -3 and it is in row 5 for the last column
I cannot use the output I get by:
print(np.where(arr2D == np.amin(arr2D, axis = 0)))
Or I don't understand the output or that's not the right way to get the aquivalent function max (min) of matlab.
Could you help me?
UPDATE:
I forgot to say that the matrix is float and not integer. I used integer just for the example
np.amin or np.min returns the min values along an axis
np.amin(arr2D, axis=0)
Out:
array([ 1, 5, 4, -3])
np.argmin returns the indices
np.argmin(arr2D, axis=0)
Out:
array([4, 3, 4, 5])
To get the desired output you can use np.vstack and transpose the array
np.vstack([np.amin(arr2D, axis=0), np.argmin(arr2D, axis=0)]).T
Out:
array([[ 1, 4],
[ 5, 3],
[ 4, 4],
[-3, 5]])
Use this code (you can simply make a function out of it):
import numpy as np
arr2D = np.array([[11, 12, 13, 34],
[14, 15, 16, 3],
[17, 15, 11, 1],
[7, 5, 11, 4],
[1, 12, 4, 4],
[12, 14, 15,-3]])
flat = arr2D.flatten()
arrayIndex = flat.tolist().index(min(flat))
// results
rowIndex = int(minIndex/arr2D.shape[0])
columnIndex = minIndex % arr2D.shape[1]
The situation is the following:
Lets say I have two arrays, x and y:
Input:
x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14]
y = [2,6,9,13]
Expected output:
arr1 = [2,3,4,5]
arr2 = [6,7,8]
arr3 = [9,10,11,12]
I would like to create a python script that can let me split up array x into multiple arrays based on the values of array y as the end points.
So x will split up between 2 and 6, then between 6 and 9, then between 9 and 13 in this example.
I am not sure how to get started on this, I am a beginner. I would appreciate the help and I would love to know how you broke down the problem to solve it? Thank you!
Find the index of x based on value in y and then use indexing
arr = []
for i in range(len(y)-1):
arr.append(x[x.index(y[i]):x.index(y[i+1])])
arr
[[2, 3, 4, 5], [6, 7, 8], [9, 10, 11, 12]]
This works if there are duplicates in the array,
x = [2,3,4,5,6,7,7,8,9,9,10,11,11,12,13,14,15]
y = [2,6,9,13]
arr = []
for i in range(len(y)-1):
arr.append(x[x.index(y[i]):x.index(y[i+1])])
[[2, 3, 4, 5], [6, 7, 7, 8], [9, 9, 10, 11, 11, 12]]
For x sorted, we can use np.searchsorted with np.split to split x using the indices where y is contained in x:
import numpy as np
i = np.searchsorted(x, y)
np.split(x,i+1)[1:-1]
# [array([3, 4, 5, 6]), array([7, 8, 9]), array([10, 11, 12, 13])]
You are somewhat inconsistent in your expected output, or I don`t get the pattern behind it, but this should get you close to what you want
x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14]
y = [2,6,9,13]
m = []
for i in range(len(y) - 1):
m += [x[y[i] - 1:y[i+1] - 1]]
print(m)
Output
[[2, 3, 4, 5], [6, 7, 8], [9, 10, 11, 12]]
This question already has answers here:
Selecting Random Windows from Multidimensional Numpy Array Rows
(2 answers)
Closed 3 years ago.
I have an m x n numpy array arr, and for each column of arr, I have a given range of rows that I want to access.
I have an n x 1 array vec that describes when this range starts.
The range has some constant duration d.
How can I extract this d x n array of interest efficiently?
Can this be done by clever slicing?
My initial thought was to try something like:
arr = np.tile(np.arange(10),(4,1)).T
vec = np.array([3,4,5,4])
d = 3
vec_2 = vec+d
out = arr[vec:vec2,np.arange(n)]
But this gives the following error:
TypeError: only integer scalar arrays can be converted to a scalar index
The desired output would be the following array:
array([[3, 4, 5, 4],
[4, 5, 6, 5],
[5, 6, 7, 6],
[6, 7, 8, 7])
I could loop over d, but performance is important for this piece of code so I would prefer to vectorize it.
In [489]: arr=np.arange(24).reshape(6,4)
In [490]: vec=np.array([0,2,1,3])
Taking advantage of the recent expansion of linspace to generate several arrays:
In [493]: x = np.linspace(vec,vec+2,3).astype(int)
In [494]: x
Out[494]:
array([[0, 2, 1, 3],
[1, 3, 2, 4],
[2, 4, 3, 5]])
In [495]: arr[x, np.arange(4)]
Out[495]:
array([[ 0, 9, 6, 15],
[ 4, 13, 10, 19],
[ 8, 17, 14, 23]])
the column iteration approach:
In [498]: np.stack([arr[i:j,k] for k,(i,j) in enumerate(zip(vec,vec+3))],1)
Out[498]:
array([[ 0, 9, 6, 15],
[ 4, 13, 10, 19],
[ 8, 17, 14, 23]])
Is there a way to change the order of the columns in a numpy 2D array to a new and arbitrary order?
For example, I have an array
array([[10, 20, 30, 40, 50],
[ 6, 7, 8, 9, 10]])
and I want to change it into, say
array([[10, 30, 50, 40, 20],
[ 6, 8, 10, 9, 7]])
by applying the permutation
0 -> 0
1 -> 4
2 -> 1
3 -> 3
4 -> 2
on the columns. In the new matrix, I therefore want the first column of the original to stay in place, the second to move to the last column and so on.
Is there a numpy function to do it? I have a fairly large matrix and expect to get even larger ones, so I need a solution that does this quickly and in place if possible (permutation matrices are a no-go)
Thank you.
This is possible in O(n) time and O(n) space using fancy indexing:
>>> import numpy as np
>>> a = np.array([[10, 20, 30, 40, 50],
... [ 6, 7, 8, 9, 10]])
>>> permutation = [0, 4, 1, 3, 2]
>>> idx = np.empty_like(permutation)
>>> idx[permutation] = np.arange(len(permutation))
>>> a[:, idx] # return a rearranged copy
array([[10, 30, 50, 40, 20],
[ 6, 8, 10, 9, 7]])
>>> a[:] = a[:, idx] # in-place modification of a
Note that a[:, idx] is returning a copy, not a view. An O(1)-space solution is not possible in the general case, due to how numpy arrays are strided in memory.
The easiest way in my opinion is:
a = np.array([[10, 20, 30, 40, 50],
[6, 7, 8, 9, 10]])
print(a[:, [0, 2, 4, 3, 1]])
the result is:
[[10 30 50 40 20]
[6 8 10 9 7 ]]
I have a matrix based solution for this, by post-multiplying a permutation matrix to the original one. This changes the position of the elements in original matrix
import numpy as np
a = np.array([[10, 20, 30, 40, 50],
[ 6, 7, 8, 9, 10]])
# Create the permutation matrix by placing 1 at each row with the column to replace with
your_permutation = [0,4,1,3,2]
perm_mat = np.zeros((len(your_permutation), len(your_permutation)))
for idx, i in enumerate(your_permutation):
perm_mat[idx, i] = 1
print np.dot(a, perm_mat)
If you're looking for any random permuation, you can do it in one line if you transpose columns into rows, permute the rows, then transpose back:
a = np.random.permutation(a.T).T