Get element of a array at specified index - python

I have two Numpy-Arrays:
B: Shape: (20, 20, 4, 3, 4)
S: Shape: (20, 20, 4, 3)
The two arrays are corresponding, so for each element in S exists a Array with 4 Elements in B.
I use the argmax-function on S to get the index of the maximum value (e.g. 1929)
Now my question is how do i get the array in B with the given index?
When i call B.item(index), i get just a single element, not the array.

argmax works over the flattened array by default, so you need to unravel that index to use it on another NDarray:
out = B[np.unravel_index(index, S.shape)]
The 1929th element of the flattened B array (which is what B.item(index) gives you) is only a single value, since it's flattened and has no ND structure at that point.

Try:
B[np.where(B == np.amax(B))]

Related

numpy sum of each array in a list of arrays of different size

Given a list of numpy arrays, each of different length, as that obtained by doing lst = np.array_split(arr, indices), how do I get the sum of every array in the list? (I know how to do it using list-comprehension but I was hoping there was a pure-numpy way to do it).
I thought that this would work:
np.apply_along_axis(lambda arr: arr.sum(), axis=0, arr=lst)
But it doesn't, instead it gives me this error which I don't understand:
ValueError: operands could not be broadcast together with shapes (0,) (12,)
NB: It's an array of sympy objects.
There's a faster way which avoids np.split, and utilizes np.reduceat. We create an ascending array of indices where you want to sum elements with np.append([0], np.cumsum(indices)[:-1]). For proper indexing we need to put a zero in front (and discard the last element, if it covers the full range of the original array.. otherwise just delete the [:-1] indexing). Then we use the np.add ufunc with np.reduceat:
import numpy as np
arr = np.arange(1, 11)
indices = np.array([2, 4, 4])
# this should split like this
# [1 2 | 3 4 5 6 | 7 8 9 10]
np.add.reduceat(arr, np.append([0], np.cumsum(indices)[:-1]))
# array([ 3, 18, 34])

Referencing elements in n-dimensional Numpy arays, when the dimensionality is variable

I'd like to be able to reference an element of a Numpy n-dimensional array when the shape of the array itself is variable.
For a 4-D array, I know I'd be able to access some specific element index (let's say the very first one for argument) by direct referencing, for example
array[1, 1, 1, 1]
But what if the next iteration I only had a 3-dimension array? I'd need;
array[1, 1, 1]
And then a 6-dimension array? Then I'd need
array[1, 1, 1, 1, 1, 1]
Assuming that I know the appropriate index for each case, how do I go about programatically referencing array indices when the shape can change?
Thanks
you can always reshape the array and expand the index:
import numpy as np
a = np.arange(10*100*77*10*10).reshape(10,100,77,10,10)
print(a[1,2,5,9,9])
#output: 785999
def new_index(index, array):
shape = array.shape
terms = [v*np.prod(shape[i+1:]) for i,v in enumerate(index)]
return int(sum(terms))
# make a 1-D array
oneD = a.reshape(np.prod(a.shape))
print(oneD[new_index([1,2,5,9,9], a)])
#output: 785999
I'm assuming there's a numpy function that does this but I don't know it off the top of my head
hpaulj had the answer I was after. I'd tried referencing via a list (created by appending values with increasing dimension), but not via a tuple.
With the variable dimension index to be accessed as a list, first convert to a tuple, and then reference;
list_index = [1,1,1,1]
tuple_index = tuple(list_index)
result = array[tuple_index]

How do I in a sense "juggle" elements in ndarrays?

What I mean by this is imagine you have an ndarray a with shape (2,3,4). I want to define another ndarray b with shape (3,2,4) such that
b[i][j][k] = a[j][i][k]
Matrix operations only apply to the last 2 index places. If there is a way to make matrix operations act on any 2 chosen index places then everything can be solved.
Thank you
On the same lines of your thought, you can use numpy.einsum() to achieve what you want.
In [21]: arr = np.random.randn(2,3,4)
In [22]: arr.shape
Out[22]: (2, 3, 4)
# swap first two dimensions
In [23]: rolled = np.einsum('ijk->jik', arr)
In [24]: rolled.shape
Out[24]: (3, 2, 4)
But pay attention to what you want to do with the resulting array because a view of the original array is returned. Thus, if you modify the rolled array, the original arr will also be affected.
Use numpy.rollaxis:
numpy.rollaxis(a, 1)
What you are looking for is probably np.transpose(..) (in fact the transpose of a 2D matrix is a specific case of this):
b = a.transpose((1, 0, 2))
Here we specify that the first index of the new matrix (b) is the second (1) index of the old matrix (a); that the second index of the new matrix is the first (0) index of the old matrix; and the third index of the new matrix is the third index (2) of the old matrix.
This thus means that if a has a.shape = (m, n, p), then b.shape = (n, m, p).

Access elements inside numpy.where index

I'm a beginner to the Python world and hope someone can answer my question. I haven an array and need to access certain indices of elements as below
x = np.random.rand(10)
x
array([ 0.56807058, 0.8404783 , 0.86835717, 0.76030882, 0.40242679,
0.22941009, 0.56842643, 0.94541468, 0.92813747, 0.95980955])
indx = np.where(x < 0.5)
indx
(array([4, 5], dtype=int64),)
However, when I try to access first element with indx[0] it returns array([4, 5], dtype=int64). What I want to do is access elements 4 and 5 inside indx. Thank you for looking into my question and any support.
np.where returns a tuple of indices. In this case the tuple contains only one array of indices. This consistent with how where handles multi-dimensional arrays. It returns a tuple containing multiple arrays which together define the indices of the non-zero elements.
To access 4 from indx you would do: indx[0][0]. The first [0] selects the first element of the indx tuple, which is array([4, 5], dtype=int64) and the second accesses an element of this array.

Numpy: 2D array access with 2D array of indices

I have two arrays, one is a matrix of index pairs,
a = array([[[0,0],[1,1]],[[2,0],[2,1]]], dtype=int)
and another which is a matrix of data to access at these indices
b = array([[1,2,3],[4,5,6],[7,8,9]])
and I want to able to use the indices of a to get the entries of b. Just doing:
>>> b[a]
does not work, as it gives one row of b for each entry in a, i.e.
array([[[[1,2,3],
[1,2,3]],
[[4,5,6],
[4,5,6]]],
[[[7,8,9],
[1,2,3]],
[[7,8,9],
[4,5,6]]]])
when I would like to use the index pair in the last axis of a to give the two indices of b:
array([[1,5],[7,8]])
Is there a clean way of doing this, or do I need to reshape b and combine the columns of a in a corresponding manner?
In my actual problem a has about 5 million entries, and b is 100-by-100, I'd like to avoid for loops.
Actually, this works:
b[a[:, :, 0],a[:, :, 1]]
Gives array([[1, 5],
[7, 8]]).
For this case, this works
tmp = a.reshape(-1,2)
b[tmp[:,0], tmp[:,1]]
A more general solution, whenever you want to use a 2D array of indices of shape (n,m) with arbitrary large dimension m, named inds, in order to access elements of another 2D array of shape (n,k), named B:
# array of index offsets to be added to each row of inds
offset = np.arange(0, inds.size, inds.shape[1])
# numpy.take(B, C) "flattens" arrays B and C and selects elements from B based on indices in C
Result = np.take(B, offset[:,np.newaxis]+inds)
Another solution, which doesn't use np.take and I find more intuitive, is the following:
B[np.expand_dims(np.arange(B.shape[0]), -1), inds]
The advantage of this syntax is that it can be used both for reading elements from B based on inds (like np.take), as well as for assignment.
You can test this by using, e.g.:
B = 1/(np.arange(n*m).reshape(n,-1) + 1)
inds = np.random.randint(0,B.shape[1],(B.shape[0],B.shape[1]))

Categories