Reputation: 1694
Given a flatten NxN array in numpy, I'd like to find the minimum value, and its offset in the array. I've managed to find the minimum value, but is it possible to identify the offset (which row and which column)?
In the example below, a = 0.5, how can I know if it is 0.5 from [1,0], or [2,1]?
from numpy import *
value = 0
NUM_NODE = 5
EDGE = array(zeros((NUM_NODE, NUM_NODE)))
EDGE = [[ 0., 0., 0., 0., 0. ],
[ 0.5, 0., 0., 0., 0. ],
[ 1., 0.5, 0., 0., 0. ],
[ 1.41421356, 1.11803399, 1., 0., 0. ],
[ 1., 1.11803399, 1.41421356, 1., 0. ]]
a = reshape(EDGE, NUM_NODE*NUM_NODE)
print min(filter(lambda x : x > value, a))
Upvotes: 0
Views: 863
Reputation: 353229
You could use np.where
:
>>> edge = np.array(EDGE)
>>> edge[edge > 0].min()
0.5
>>> np.where(edge == edge[edge > 0].min())
(array([1, 2]), array([0, 1]))
which gives the x
coordinates and the y
coordinates which hit the minimum value separately. If you want to combine them, there are lots of ways, e.g.
>>> np.array(np.where(edge == edge[edge > 0].min())).T
array([[1, 0],
[2, 1]])
A few asides: from numpy import *
is a bad habit because that replaces some built-in functions with numpy's versions which work differently, and in some cases have the opposite results; ALLCAPS variable names are usually only given to constants; and your
EDGE = array(zeros((NUM_NODE, NUM_NODE)))
line doesn't do anything, because your EDGE = [[ 0., ... etc
line immediately makes a new list
and binds EDGE to it instead. You made an array and threw it away. There's also no need to call array
here; zeros
already returns an array.
Upvotes: 3
Reputation: 27226
numpy.ndenumerate
will enumerate over the array(by the way, you shouldn't lose position information with reshaping).
In [43]: a = array(EDGE)
In [44]: a
Out[44]:
array([[ 0. , 0. , 0. , 0. , 0. ],
[ 0.5 , 0. , 0. , 0. , 0. ],
[ 1. , 0.5 , 0. , 0. , 0. ],
[ 1.41421356, 1.11803399, 1. , 0. , 0. ],
[ 1. , 1.11803399, 1.41421356, 1. , 0. ]])
In [45]: min((i for i in ndenumerate(a) if i[1] > 0), key=lambda i: i[1])
Out[45]: ((1, 0), 0.5)
Or you can do it with the old way if you want every occurence:
In [11]: m, ms = float("inf"), []
In [12]: for pos, i in ndenumerate(a):
....: if not i: continue
....: if i < m:
....: m, ms = i, [pos]
....: elif i == m:
....: ms.append(pos)
....:
In [13]: ms
Out[13]: [(1, 0), (2, 1)]
Upvotes: 2