Getting index of numpy.ndarray - python

I have a one-dimensional array of the type numpy.ndarray and I want to know the index of it's max entry. After finding the max, I used
peakIndex = numpy.where(myArray==max)
to find the peak's index. But instead of the index, my script spits out
peakIndex = (array([1293]),)
I want my code to spit out just the integer 1293. How can I clean up the output?

Rather than using numpy.where, you can use numpy.argmax.
peakIndex = numpy.argmax(myArray)
numpy.argmax returns a single number, the flattened index of the first occurrence of the maximum value. If myArray is multidimensional you might want to convert the flattened index to an index tuple:
peakIndexTuple = numpy.unravel_index(numpy.argmax(myArray), myArray.shape)

To find the max value of an array, you can use the array.max() method. This will probably be more efficient than the for loop described in another answer, which- in addition to not being pythonic- isn't actually written in python. (if you wanted to take items out of the array one by one to compare, you could use ndenumerate, but you'd be sacrificing some of the performance benefits of arrays)
The reason that numpy.where() yields results as tuples is that more than one position could be equal to the max... and it's that edge case that would make something simple (like taking array[0]) prone to bugs. Per Is there a Numpy function to return the first index of something in an array?,
"The result is a tuple with first all the row indices, then all the
column indices".
Your example uses a 1-D array, so you'd get the results you want directly from the array provided. It's a tuple with one element (one array of indices), and although you can iterate over ind_1d[0] directly, I converted it to a list solely for readability.
>>> peakIndex_1d
array([ 1. , 1.1, 1.6, 1. , 1.6, 0.8])
>>> ind_1d = numpy.where( peakIndex_1d == peakIndex_1d.max() )
(array([2, 4]),)
>>> list( ind_1d[0] )
[2, 4]
For a 2-D array with 3 values equal to the max, you could use:
>>> peakIndex
array([[ 0. , 1.1, 1.5],
[ 1.1, 1.5, 0.7],
[ 0.2, 1.2, 1.5]])
>>> indices = numpy.where( peakIndex == peakIndex.max() )
>>> ind2d = zip(indices[0], indices[1])
[(0, 2), (1, 1), (2, 2)]

Related

Numpy max over only the first element of an array of pairs

I have a multidimensional numpy array consisting of tuples like below:
[[(0.56, 1),(0.25, 4), ...],[(0.11, 9), ...], ...]
The second element of each tuple is an index reference. I want to extract the tuple with the highest first value per row. Is there a way to achieve this with numpy max?
One thing I tried is playing around with the axis parameter like below:
np.max(my_array, axis=0)
But this shuffles around the pairs with the index reference not preserved. E.g. the first row in the above example would show something like [(0.56,4), ...] whereas I want it to show [(0.56,1), ...]
In plain python, you could use :
[max(row, key=lambda row: row[0]) for row in array]
Don't use tuples in numpy arrays. Convert it all to a numpy array with the last dimension being 2:
>>> a = np.array([[(0.56, 1), (0.25, 4)],[(0.11, 9), (0.19, 5)]])
>>> a.shape
(2, 2, 2)
Then:
>>> highest_val_per_row = np.argmax(a[:,:,0], axis=1)
>>> a[np.arange(a.shape[0]), highest_val_per_row]
array([[0.56, 1. ],
[0.19, 5. ]])
You can try something linke this:
lst = [[(0.56, 1),(0.25, 4)],[(0.11, 9), (0.25, 4)]]
for e in lst:
print(max(e))
However, i think there are more efficient ways of doing it.

How to check if the elements in array A exist in array B and return the index of B [duplicate]

I want to solve something like the problem detailed at Find index mapping between two numpy arrays, but where the two arrays do not necessarily contain the same set of values, although their values are unique within each array, and are sorted.
E.g. if I have two arrays:
a = np.array([1.1, 2.2, 3.3, 4.4, 5.5])
b = np.array([2.2, 3.0, 4.4, 6.0])
I want to get an array of the same length as a which gives the index into b where the matching element is, or -1 if there is no match. I.e. in this case:
map = np.array([-1, 0, -1, 2, -1])
Is there a neat, fast way to do this using np.searchsorted?
Use the searchsorted indices to do a check on matches and then mask the invalid ones with the invalid-specifier. For the matching check, do b[idx]==a with idx as those indices. Hence -
invalid_specifier = -1
idx = np.searchsorted(b,a)
idx[idx==len(b)] = 0
out = np.where(b[idx]==a, idx, invalid_specifier)

How to threshold values in python without if statement (to zero if below threshold, same if above)

I want to do an inline comparison without writing 'If statements' in Python. If the value meets the threshold condition, it should be unchanged. If it doesn't the value should be set to 0.
In Python I don't seem to be allowed to apply a boolean operator to a list directly. In Matlab, it's convenient that 'True' gives a '1' and 'False' gives a zero in array operations. This is matlab-like, but won't work in python (maybe would with numpy?). Pseudocode example:
a = [1.5, 1.3, -1.4, -1.2]
a_test_positive = a>0 # Gives [1, 1, 0, 0]
positive_a_only = a.*a>0
Desired result:
positive_a_only>> [1.5, 1.3, 0, 0]
What is the best way to do this in python?
You need -
a = [1.5, 1.3, -1.4, -1.2]
positive_a_only = [i if i>0 else 0 for i in a]
print(positive_a_only)
Output
[1.5, 1.3, 0, 0]
This is known as a List Comprehension
According to your input and expected output, this is a "pythonic" way to do this
List comprehensions provide a concise way to create lists. Common
applications are to make new lists where each element is the result of
some operations applied to each member of another sequence or
iterable, or to create a subsequence of those elements that satisfy a
certain condition.
You use case is kind of made for this :)
It may worth looking at Numpy if you are working with numerical arrays.
import numpy as np
a = np.array([1.5, 1.3, -1.4, -1.2])
a[a < 0] = 0
# [ 1.5 1.3 0. 0. ]
The best answer I have found so far is to enumerate and loop through the array, using the python operator for the threshold or comparison logic.
The key is to multiply the index element by the logical comparison. e.g.
a = 1.5
a_positive = a * (a>0)
print(a)
Returns the value of 1.5 as expected, and returns 0 if a is negative.
Here's the example then with the full list:
a = [1.5, 1.3 -1.4, -1.2]
for i, element in enumerate(a):
a[i] = element*(element>0)
print(a)
[1.5, -0.0, -0.0]
Hope that helps someone!

Python, numpy.array slicing, altering array values with slices

I have a Task for numerical integration in which we approximate integral with quadrature formula. My problem is that the task needs me to avoid loops and use vectorized variant, which would be a slice?!
I have np.array object with n values and i have to alter each value of this array using a specific formula. The problem is that the value of this array at point i ist used in the formula to alter the position in. With a for loop it would be easy:
x = np.array([...])
for i in range(0,n):
x[i]=f(x[i]+a)*b`
(a,b some othe variables)
How do i do this with slices? I Have to do this for all elements of the array so it would be something like:
x[:]=f(x[???]+a)*b
And how do i get the right position from my array in to the formula? A slicing instruction like x[:] just runs through my whole object. Is there a way to somehow save the index i am currently at?
I tried to search but found nothing. The other problem is that i do not even know how to properly put the search request...
You may be confusing two issues
modifying all elements of an array
calculating values for all elements of an array
In
x = np.array([...])
for i in range(0,n):
x[i]=f(x[i]+a)*b`
you change elements of x one by one, and also pass them one by one to f.
x[:] = ... lets you change all elements of x at once, but the source (the right hand side of the equation) has to generate all those values. But usually you don't need to assign values. Instead just use x = .... It's just as fast and memory efficient.
Using x[:] on the RHS does nothing for you. If x is a list this makes a copy; if x is an array is just returns a view, an array with the same values.
The key question is, what does your f(...) function accept? If it uses operations like +, * and functions like np.sin, you can give it an array, and it will return an array.
But if it only works with scalars (that includes using functions like math.sin), the you have to feed it scalars, i.e. x[i].
Let's try to unpack that comment (which might be better as an edit to the original question)
I have an interval which has to be cut in picies.
x = np.linspace(start,end,pieceAmount)
function f
quadrature formula
b (weights or factors)
c (function values)
b1*f(x[i]+c1)+...+bn*f(x[i]+cn)
For example
In [1]: x = np.arange(5)
In [2]: b = np.arange(3)
In [6]: c = np.arange(4,7)*.1
We can do the x[i]+c for all x and c with broadcasting
In [7]: xc = x + c[:,None]
In [8]: xc
Out[8]:
array([[ 0.4, 1.4, 2.4, 3.4, 4.4],
[ 0.5, 1.5, 2.5, 3.5, 4.5],
[ 0.6, 1.6, 2.6, 3.6, 4.6]])
If f is a function like np.sin that takes any array, we can pass xc to that, getting back a like sized array.
Again with broadcasting we can do the b[n]*f(x[i]+c[n]) calculation
In [9]: b[:,None]* np.sin(xc)
Out[9]:
array([[ 0. , 0. , 0. , -0. , -0. ],
[ 0.47942554, 0.99749499, 0.59847214, -0.35078323, -0.97753012],
[ 1.12928495, 1.99914721, 1.03100274, -0.88504089, -1.98738201]])
and then we can sum, getting back an array shaped just like x:
In [10]: np.sum(_, axis=0)
Out[10]: array([ 1.60871049, 2.99664219, 1.62947489, -1.23582411, -2.96491212])
That's the dot or matrix product:
In [11]: b.dot(np.sin(xc))
Out[11]: array([ 1.60871049, 2.99664219, 1.62947489, -1.23582411, -2.96491212])
And as I noted earlier we can complete the action with
x = b.dot(f(x+c[:,None])
The key to a simple expression like this is f taking an array.

How to sort a numpy array into a specific order, specified by a separate list, based on the relative sizes of the values in the array

Within a piece of code I have a numpy array already constructed, and I want to sort this 1st array given a specific order specified in a list. The result will be a 3rd array (new_values).
The 1st array has the values to be sorted.
values = numpy.array([10.0, 30.1, 50, 40, 20])
The list provides the order given by the indices of the values in new_values which should be in descending order where 0 corresponds to the largest number.
order=[0, 3, 1, 4, 2].
So,
new_values[0] > new_values[3] > new_values[1] > new_values[4] > new_values[2]
I tried to find a specific sort function to accomplish this such as argsort or with a key, however I did not understand how to adapt these to this situation.
Is there a simple quick method to accomplish this as I will be doing this for many iterations. I am willing to change the 2nd array, order, to specify the indices in another way if this was advantageous to sorting with a better method.
Currently I am using the following for loop.
size=len(values)
new_values = np.zeros(size)
values = sorted(values,reverse=True)
for val in range(0, size):
new_values[int(order[val])] = values[val]
Thank you in advance!
You can simply use indexing for that :
>>> import numpy as np
>>> values = np.array([10.0, 30.1, 50, 40, 20])
>>> order=[0, 3, 1, 4, 2]
>>> sorted_array=values[order]
>>> sorted_array
array([ 10. , 40. , 30.1, 20. , 50. ])
Also as #Divakar mentioned in comment if you want the following condition :
new_values[0] > new_values[3] > new_values[1] > new_values[4] > new_values[2]
You can do :
>>> values[order]=np.sort(values)[::-1]
>>> values
array([ 50. , 30.1, 10. , 40. , 20. ])

Categories

Resources