A question about nested indexing of `numpy` arrays - numpy

I'm trying to understand what the following does at a conceptual level. Let's say we have two numpy arrays of random integers
arr1
array([[2, 2, 2, 2, 1],
[1, 3, 1, 3, 2],
[2, 2, 2, 1, 3],
[1, 1, 1, 3, 2]])
arr2
array([[1, 3, 1, 1, 3, 3, 2, 2],
[2, 3, 2, 2, 2, 3, 2, 1],
[3, 3, 3, 1, 1, 3, 3, 3],
[1, 1, 2, 1, 2, 1, 1, 1]])
Then, I do a nested indexing of the second array arr2 into the first one arr1, obtaining
arr1[arr2,:]
array([[[1, 3, 1, 3, 2],
[1, 1, 1, 3, 2],
[1, 3, 1, 3, 2],
[1, 3, 1, 3, 2],
[1, 1, 1, 3, 2],
[1, 1, 1, 3, 2],
[2, 2, 2, 1, 3],
[2, 2, 2, 1, 3]],
[[2, 2, 2, 1, 3],
[1, 1, 1, 3, 2],
[2, 2, 2, 1, 3],
[2, 2, 2, 1, 3],
[2, 2, 2, 1, 3],
[1, 1, 1, 3, 2],
[2, 2, 2, 1, 3],
[1, 3, 1, 3, 2]],
[[1, 1, 1, 3, 2],
[1, 1, 1, 3, 2],
[1, 1, 1, 3, 2],
[1, 3, 1, 3, 2],
[1, 3, 1, 3, 2],
[1, 1, 1, 3, 2],
[1, 1, 1, 3, 2],
[1, 1, 1, 3, 2]],
[[1, 3, 1, 3, 2],
[1, 3, 1, 3, 2],
[2, 2, 2, 1, 3],
[1, 3, 1, 3, 2],
[2, 2, 2, 1, 3],
[1, 3, 1, 3, 2],
[1, 3, 1, 3, 2],
[1, 3, 1, 3, 2]]])
which is a new array with shape (4,8,5). It is not clear to me how should I interpret this new object, and how the entries of the two arrays are actually combined together.

Reference on numpy ndarray indexing with integer arrays
TLDR:
out = arr1[arr2, :]
out[i, j, k] == arr1[ arr2[i, j], k ] # for all valid indices i,j,k
Intuition:
The values inside arr2 are being used independently/separately to index the first axis of arr1, and the results are placed into a new array with the same shape as arr2.

Related

How to add MutableList to an other MutableList - Kotlin?

Good afternoon dear StackOverflow community,
I encounter a problem using MutableList in Kotlin. More specifically, I do not succeed to add a MutableList inside a MutableList.
For instance, with the example thereafter
fun main() {
var mutableListIndex: MutableList<Int> = mutableListOf<Int>()
var mutableListTotal: MutableList<MutableList<Int>> = mutableListOf<MutableList<Int>>()
for(i in 0..5) {
mutableListIndex.add(i)
println(mutableListIndex)
mutableListTotal.add(mutableListIndex)
println(mutableListTotal)
}
}
I get the following result
[0]
[[0]]
[0, 1]
[[0, 1], [0, 1]]
[0, 1, 2]
[[0, 1, 2], [0, 1, 2], [0, 1, 2]]
[0, 1, 2, 3]
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
[0, 1, 2, 3, 4]
[[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]
[0, 1, 2, 3, 4, 5]
[[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]]
While, I am expecting the result thereafter
[0]
[[0]]
[0, 1]
[[0], [0, 1]]
[0, 1, 2]
[[0], [0, 1], [0, 1, 2]]
[0, 1, 2, 3]
[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3]]
[0, 1, 2, 3, 4]
[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4]]
[0, 1, 2, 3, 4, 5]
[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4, 5]]
I do not succeed to understand where I am wrong as in my opinion the code from the stricly speaking algorythm point of view is good.
Can someone help and explain me my error ?
Yours faithfully
Following the advice of Sir Animesh Sahu above, I finally follow this solution:
fun main() {
var mutableListIndex: MutableList<Int> = mutableListOf<Int>()
var mutableListTotal: MutableList<MutableList<Int>> = mutableListOf<MutableList<Int>>()
for(i in 0..5) {
mutableListIndex.add(i)
println(mutableListIndex)
mutableListTotal.add(mutableListIndex.toMutableList())
println(mutableListTotal)
}
}
Which give:
[0]
[[0]]
[0, 1]
[[0], [0, 1]]
[0, 1, 2]
[[0], [0, 1], [0, 1, 2]]
[0, 1, 2, 3]
[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3]]
[0, 1, 2, 3, 4]
[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4]]
[0, 1, 2, 3, 4, 5]
[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4, 5]]
Thank you very much all for your prompt reply and your help
Yours faithfully
You always pass in the same reference of mutableListIndex to be added into mutableListTotal. So on every position you have the same object.
Then you add a new item into your first list and every reference to it points to the updated List, with one more item.
To get an independent object, that is not updated every time your first reference is updated, you first need to create a copy of the List and only add the copy into your second list. This way an update to your initial list will not be reflected into your copies of the first list.
import java.util.List.copyOf
fun main() {
...
mutableListTotal.add(copyOf(mutableListIndex))
...
}

Taking different columns from each 2D slice of a 3D numpy array

Assume the following 3D numpy array:
array([[[4, 1, 3, 5, 0, 1, 5, 4, 3],
[2, 3, 3, 2, 1, 0, 5, 5, 4],
[5, 3, 0, 2, 2, 2, 5, 3, 2],
[0, 3, 1, 0, 2, 4, 1, 1, 5],
[2, 0, 0, 1, 4, 0, 3, 5, 3]],
[[2, 2, 4, 1, 3, 4, 1, 1, 5],
[2, 2, 3, 5, 5, 4, 0, 2, 0],
[4, 0, 5, 3, 1, 3, 1, 1, 1],
[4, 5, 0, 0, 5, 3, 3, 2, 4],
[0, 3, 4, 5, 4, 5, 4, 2, 3]],
[[1, 3, 2, 2, 0, 4, 5, 0, 2],
[5, 0, 5, 2, 3, 5, 5, 3, 1],
[0, 5, 3, 2, 2, 0, 4, 2, 3],
[4, 4, 0, 3, 2, 1, 5, 3, 0],
[0, 0, 2, 4, 0, 5, 2, 0, 0]]])
Given a list [3, 4, 8],
is it possible to slice the given tensor without using a for loop?
For example to take the 3rdth column from [0, :, :], 4th column from [1, :, :] and 8th column from [2, :, :] to obtain:
array([[5, 2, 2, 0, 1],
[3, 5, 1, 5, 4],
[2, 1, 3, 0, 0]])
Here's one way with np.take_along_axis -
In [73]: idx = np.array([3,4,8])
# a is input array
In [72]: np.take_along_axis(a,idx[:,None,None],axis=2)[:,:,0]
Out[72]:
array([[5, 2, 2, 0, 1],
[3, 5, 1, 5, 4],
[2, 1, 3, 0, 0]])
Another with the explicit integer-indexing -
In [79]: a[np.arange(len(idx)),:,idx]
Out[79]:
array([[5, 2, 2, 0, 1],
[3, 5, 1, 5, 4],
[2, 1, 3, 0, 0]])

Numpy Where () with All() on a 2D matrix

A= np.random.randint(5, size=(25, 4, 4))
U= np.unique(A, axis =0 )
results = np.where((A==U[0]).all(axis=-1))
Using this Where function matches individual rows, I would like to match the entire 4x4 array not just individual rows.
here are example results:
(array([ 1, 97, 97, 97, 97], dtype=int64), array([0, 0, 1, 2, 3], dtype=int64))
if all four rows were matched the results would contain the same index 4 times as its for the index 97 above, a single row was matched with the index "1".
I assume if the entire array was matched then just one index would have been returned.
An example of desired output if multiple indexes are supplied for one array:
(array([97, 97, 97, 97], dtype=int64), array([0, 1, 2, 3], dtype=int64)
np.where((A.reshape(A.shape[0],-1) == U[0].reshape(-1)).all(axis=1))
Let's see an example
>>> A = np.random.randint(5, size=(25, 4, 4))
>>> A[:3,...]
array([[[0, 2, 0, 1],
[1, 0, 3, 0],
[4, 1, 1, 2],
[0, 1, 0, 0]],
[[1, 3, 2, 3],
[2, 4, 2, 1],
[3, 3, 2, 3],
[4, 2, 1, 1]],
[[4, 0, 3, 3],
[1, 0, 4, 4],
[0, 0, 2, 3],
[4, 1, 2, 2]]])
>>> U = np.unique(A, axis=0)
>>> U[0]
array([[0, 2, 0, 1],
[1, 0, 3, 0],
[4, 1, 1, 2],
[0, 1, 0, 0]])
Now you to want find U[0] in A if I understood correctly. It's easier to match row by row, so let's reshape the 4x4 arrays into rows
>>> A.reshape(A.shape[0], -1)[:3,...]
array([[0, 2, 0, 1, 1, 0, 3, 0, 4, 1, 1, 2, 0, 1, 0, 0],
[1, 3, 2, 3, 2, 4, 2, 1, 3, 3, 2, 3, 4, 2, 1, 1],
[4, 0, 3, 3, 1, 0, 4, 4, 0, 0, 2, 3, 4, 1, 2, 2]])
>>> U[0].reshape(-1)
array([0, 2, 0, 1, 1, 0, 3, 0, 4, 1, 1, 2, 0, 1, 0, 0])
Now we can compare them with np.where but if we're not careful we'll get an elementwise comparison, so we need to use np.all(axis=1) to be sure to compare them row by row:
>>> np.where(np.all(A.reshape(25, -1) == U[0].reshape(-1), axis=1))
(array([0]),)
EDIT it just occurred to me you can use multiple axes with np.all and avoid reshaping altogether:
np.where((A == U[0]).all(axis=(1,2)))

Python - numpy mgrid and reshape

Can someone explain to me what the second line of this code does?
objp = np.zeros((48,3), np.float32)
objp[:,:2] = np.mgrid[0:8,0:6].T.reshape(-1,2)
Can someone explain to me what exactly the np.mgrid[0:8,0:6] part of the code is doing and what exactly the T.reshape(-1,2) part of the code is doing?
Thanks and good job!
The easiest way to see these is to use smaller values for mgrid:
In [11]: np.mgrid[0:2,0:3]
Out[11]:
array([[[0, 0, 0],
[1, 1, 1]],
[[0, 1, 2],
[0, 1, 2]]])
In [12]: np.mgrid[0:2,0:3].T # (matrix) transpose
Out[12]:
array([[[0, 0],
[1, 0]],
[[0, 1],
[1, 1]],
[[0, 2],
[1, 2]]])
In [13]: np.mgrid[0:2,0:3].T.reshape(-1, 2) # reshape to an Nx2 matrix
Out[13]:
array([[0, 0],
[1, 0],
[0, 1],
[1, 1],
[0, 2],
[1, 2]])
Then objp[:,:2] = sets the 0th and 1th columns of objp to this result.
The second line creates a multi-dimensional mesh grid, transposes it, reshapes it so that it represents two columns and inserts it into the first two columns of the objp array.
Breakdown:
np.mgrid[0:8,0:6] creates the following mgrid:
>> np.mgrid[0:8,0:6]
array([[[0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3],
[4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6],
[7, 7, 7, 7, 7, 7]],
[[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5]]])
The .T transposes the matrix, and the .reshape(-1,2) then reshapes it into two a two-column array shape. These two columns are then the correct shape to replace two columns in the original array.

Generate a 'closeness to center' matrix in numpy

I think this should be easy, but I'm not sure of an efficient way to do it.
I'd like to build a matrix in numpy that has the cityblock / manhattan closeness to the center of the matrix, in numpy, for any odd size.
For a size of 5, the output would be:
array([[0, 1, 2, 1, 0],
[1, 2, 3, 2, 1],
[2, 3, 4, 3, 2],
[1, 2, 3, 2, 1],
[0, 1, 2, 1, 0]])
What's the best way of doing this? Thanks
Easy and efficient with broadcasting -
def closeness_manhattan(N):
r = np.arange(N)
a = np.minimum(r,r[::-1])
return a[:,None] + a
Sample runs -
In [14]: closeness_manhattan(4)
Out[14]:
array([[0, 1, 1, 0],
[1, 2, 2, 1],
[1, 2, 2, 1],
[0, 1, 1, 0]])
In [15]: closeness_manhattan(5)
Out[15]:
array([[0, 1, 2, 1, 0],
[1, 2, 3, 2, 1],
[2, 3, 4, 3, 2],
[1, 2, 3, 2, 1],
[0, 1, 2, 1, 0]])