Numpy minimum with functional arg - python

Is there a way of computing a minimum index value of an array after application of a function (i.e. the equivalent of matlab find)?
In other words consider something like:
a = [1,-3,-10,3]
np.find_max(a,lambda x:abs(x))
Should return 2.
I could write a loop for this obviously but I assume it would be faster to use an inbuilt numpy function if one existed.

Use argmax, according to the documentation:
numpy.argmax(a, axis=None, out=None)
Returns the indices of
the maximum values along an axis.
Parameters: a : array_like Input array. axis : int, optional By
default, the index is into the flattened array, otherwise along the
specified axis. out : array, optional If provided, the result will be
inserted into this array. It should be of the appropriate shape and
dtype. Returns: index_array : ndarray of ints Array of indices into
the array. It has the same shape as a.shape with the dimension along
axis removed. See also ndarray.argmax, argmin
amax The maximum value along a given axis. unravel_index Convert a
flat index into an index tuple. Notes
In case of multiple occurrences of the maximum values, the indices
corresponding to the first occurrence are returned.
import numpy as np
a = [1, -3, -10, 3]
print(np.argmax(np.abs(a)))
Output:
2

Related

How to transform 2D array using values as another array's indices?

I have a 2D array with indices refering to another array:
indexarray = np.array([[0,0,1,1],
[1,2,3,0]])
The array which these indices refer to is:
valuearray = np.array([8,7,6,5])
I would like to get an array with the numbers from valuearray in the shape of indexarray, each item in this array corresponds to the value in valuearray with the index on the same location in indexarray, ie:
targetarray = np.array([[8,8,7,7],
[7,6,5,8]])
How can I do this without iteration?
What I do now to achieve this is:
np.apply_along_axis(func1d = lambda row: valuearray[row],axis=0,arr = indexarray)
If there is a simpler way, I am interested.
One way is to flatten the index array and get the values and reshape it back as follows.
targetarray = valuearray[indexarray.flatten()].reshape(indexarray.shape)

Call numpy ravel and include an interger multi-index

I have 4-dimensional array. I am going to turn it into a 1-dim array. I use numpy ravel and it works fin with the default parameters.
However I would also like the positions/indices in the 4-dim array.
I want something like this as row in my output.
x,y,z,w,value
With x being the first dimension of my initial array and so on.
The obvious approach is iteration, however I was told to avoid it when I can.
for i in range(test.shape[0]):
for j in range(test.shape[1]):
for k in range(test.shape[2]):
for l in range(test.shape[3]):
print(i,j,k,l,test[(i,j,k,l)])
It will be to slow when I use a larger dataset.
Is there a way to configure ravel to do this or any other approach faster than iteration.
Use np.indices with sparse=False, combined with np.concatenate to build the array. np.indices provides the first n columns, and np.concatenate appends the last one:
test = np.random.randint(10, size=(3, 5, 4, 2))
index = np.indices(test.shape, sparse=False) # shape: (4, 3, 5, 4, 2)
data = np.concatenate((index, test[None, ...]), axis=0).reshape(test.ndim + 1, -1).T
A more detailed breakdown:
index is a (4, *test.shape) array, with one element per dimension.
To make test concatenatable with index, you need to prepend a unit dimension, which is what test[None, ...] does. None is synonymous with np.newaxis, and Ellipsis, or ..., means "all the remaining dimensions".
When you concatenate along axis=0, you are appending test to the array of indices. Each element of index along the first axis is now a 5-element array containing the index followed by the value. The remaining axes reflect the shape of test, but besides that, you have what you want.
The goal is to flatten out the trailing dimensions, so you get a (5, N) array, where N = np.prod(test.shape). Thats what the final reshape does. test.ndim + 1 is the size of the index +1 for the value. -1 can appear exactly once in a reshape. It means "product of all the remaining dimensions".

Sorting arrays by their last argument

I want to sort a numpy array of arrays based on their last entry.
For example, say we have this array of arrays:
a=np.array([np.array([1,2,5]),np.array([1,3,0]),np.array([1,4,-17])])
I want to return the array sorted this way:
np.array([np.array([1,4,-17]),np.array([1,3,0]) ,np.array([1,2,5]) ])
I.e. as -17 <= 0 <= 5, last array becomes the first one, and so on. Elements within each array must not be altered.
I suppose numpy has a builtin but I haven't been able to find it.

extracting vectors from an array using logical indexing

I have the following numpy arrays:
a truth table of (nx1), and a matrix of (nxk) where n is 5 and k is 2 in this example.
btable = np.array([[True],[False],[False],[True],[True]])
bb=np.array([[1.842,4.607],[5.659,4.799],[6.352,3.290],[2.904,4.612],[3.231,4.939]])
I would like to extract the vectors in bb according the indexing values in btable.
I tried choicebb=bb[btable==True] which gets me the result
[ 1.84207953 2.90401653 3.23197916]
choicebb=bb[btable] gets me the same results as well.
What I want instead is
[[1.842,4.607]
[2.904,4.612]
[3.231,4.939]]
I also tried
choicebb=bb[btable==True,:]
but then I would get
---> 13 choicebb=bb[btable==True,:]
14 print(choicebb)
IndexError: too many indices for array
This can be easily done in matlab with choicebb=bb(btable,:);
Get the 1D version of the mask with np.ravel() or slice out the first column with [:,0] and use it for logical indexing into the data array, like so -
bb[btable.ravel()]
bb[btable[:,0]]
Note that bb[btable.ravel()] is essentially - bb[btable.ravel(),:]. In NumPy, we could skip mentioning the trailing axes if all elements are to be selected, that's why it simplified to bb[btable.ravel()].
Explanataion : To index into a single axis and such that it select all elements along the rest of the axes, we need to feed in a 1D array (boolean or integer array) along that axis and use : along the leftover axes. In our case, we are indexing into the first axis to select rows, so we need to feed in a boolean array along that axis and : along the rest of axes.
When we are feeding the 2D version of the mask, it indexes along those corresponding multiple axes. So, when we feed in (N,1) shaped boolean array, we are selecting correct rows, but also only selecting the first column elements, which is not the intended output.

numpy newaxis does not always append new axis where I want to

Why doesn't np.newaxis always append the axis where I put it? See example:
import numpy as np
M = np.array([[1,4],[2,5], [3,4]])
M[:,np.newaxis].shape
# returns (3, 1, 2)
According to the documents describing newaxis:
The added dimension is the position of the newaxis object in the selection tuple.
In your example, newaxis is in the second position of the tuple, hence the new dimension of length 1 is inserted there.
This is analogous to selecting a value at a particular index. For a three-dimensional A, you would use A[:,0] to retrieve the index 0 value from the second axis, not the third axis.
If you want to add the new axis in the last position of the tuple, you could write M[:,:,np.newaxis] or alternatively use the ellipses notation:
>>> M[...,np.newaxis].shape
(3, 2, 1)

Categories