python - una - numpy tutorial español pdf
¿Existe una función NumPy para devolver el primer índice de algo en una matriz? (13)
El paquete numpy_indexed (descargo de responsabilidad, soy su autor) contiene un equivalente vectorizado de list.index para numpy.ndarray; es decir:
sequence_of_arrays = [[0, 1], [1, 2], [-5, 0]]
arrays_to_query = [[-5, 0], [1, 0]]
import numpy_indexed as npi
idx = npi.indices(sequence_of_arrays, arrays_to_query, missing=-1)
print(idx) # [2, -1]
Esta solución ha vectorizado el rendimiento, generaliza a ndarrays y tiene varias formas de tratar con los valores perdidos.
Sé que hay un método para que una lista de Python devuelva el primer índice de algo:
>>> l = list([1, 2, 3])
>>> l.index(2)
1
¿Hay algo así para matrices NumPy?
Hay muchas operaciones en NumPy que tal vez podrían organizarse para lograr esto. Esto devolverá índices de elementos iguales al elemento:
numpy.nonzero(array - item)
A continuación, puede tomar los primeros elementos de las listas para obtener un solo elemento.
Para indexar en cualquier criterio, puedes hacer algo como lo siguiente:
In [1]: from numpy import *
In [2]: x = arange(125).reshape((5,5,5))
In [3]: y = indices(x.shape)
In [4]: locs = y[:,x >= 120] # put whatever you want in place of x >= 120
In [5]: pts = hsplit(locs, len(locs[0]))
In [6]: for pt in pts:
.....: print('', ''.join(str(p[0]) for p in pt))
4, 4, 0
4, 4, 1
4, 4, 2
4, 4, 3
4, 4, 4
Y aquí hay una función rápida para hacer lo que hace list.index (), excepto que no genera una excepción si no se encuentra. Cuidado, esto es probablemente muy lento en arreglos grandes. Probablemente puedas parchear esto en matrices si prefieres usarlo como método.
def ndindex(ndarray, item):
if len(ndarray.shape) == 1:
try:
return [ndarray.tolist().index(item)]
except:
pass
else:
for i, subarray in enumerate(ndarray):
try:
return [i] + ndindex(subarray, item)
except:
pass
In [1]: ndindex(x, 103)
Out[1]: [4, 0, 3]
Para las matrices 1D, recomendaría np.flatnonzero(array == value)[0]
, que es equivalente a np.nonzero(array == value)[0][0]
y np.where(array == value)[0][0]
pero evita la fealdad de desempaquetar una tupla de 1 elemento.
Para matrices ordenadas unidimensionales, sería mucho más simple y eficiente O (log (n)) usar numpy.searchsorted que devuelve un entero NumPy (posición). Por ejemplo,
i = np.searchsorted(np.array([1, 1, 1, 2, 3, 3, 4]), 3)
Solo asegúrese de ordenar la matriz antes si aún no está ordenada.
Sí, aquí está la respuesta dada una matriz NumPy, una array
y un valor, item
, para buscar:
itemindex = numpy.where(array==item)
El resultado es una tupla con primero todos los índices de fila, luego todos los índices de columna.
Por ejemplo, si una matriz tiene dos dimensiones y contiene su elemento en dos ubicaciones, entonces
array[itemindex[0][0]][itemindex[1][0]]
sería igual a su artículo y así lo haría
array[itemindex[0][1]][itemindex[1][1]]
Si necesita el índice de la primera aparición de un solo valor , puede usar un valor nonzero
(o where
, lo que equivale a lo mismo en este caso):
>>> t = array([1, 1, 1, 2, 2, 3, 8, 3, 8, 8])
>>> nonzero(t == 8)
(array([6, 8, 9]),)
>>> nonzero(t == 8)[0][0]
6
Si necesita el primer índice de cada uno de los muchos valores , obviamente podría hacer lo mismo que el anterior repetidamente, pero hay un truco que puede ser más rápido. A continuación se encuentran los índices del primer elemento de cada subsecuencia :
>>> nonzero(r_[1, diff(t)[:-1]])
(array([0, 3, 5, 6, 7, 8]),)
Observe que encuentra el comienzo de ambas subsecuencias de 3s y ambas subsecuencias de 8s:
[ 1 , 1, 1, 2 , 2, 3 , 8 , 3 , 8 , 8]
Así que es ligeramente diferente a encontrar la primera aparición de cada valor. En su programa, puede trabajar con una versión ordenada de t
para obtener lo que desea:
>>> st = sorted(t)
>>> nonzero(r_[1, diff(st)[:-1]])
(array([0, 3, 5, 7]),)
Si va a utilizar esto como un índice en otra cosa, puede usar índices booleanos si los arreglos son de difusión; No necesitas índices explícitos. La forma más sencilla de hacerlo es simplemente indexar según un valor de verdad.
other_array[first_array == item]
Cualquier operación booleana funciona:
a = numpy.arange(100)
other_array[first_array > 50]
El método distinto de cero toma booleanos, también:
index = numpy.nonzero(first_array == item)[0][0]
Los dos ceros son para la tupla de índices (suponiendo que first_array es 1D) y luego el primer elemento en la matriz de índices.
Solo para agregar una alternativa numba muy práctica y práctica basada en np.ndenumerate
para encontrar el primer índice:
from numba import njit
import numpy as np
@njit
def index(array, item):
for idx, val in np.ndenumerate(array):
if val == item:
return idx
# If no item was found return None, other return types might be a problem due to
# numbas type inference.
Esto es bastante rápido y trata naturalmente con matrices multidimensionales :
>>> arr1 = np.ones((100, 100, 100))
>>> arr1[2, 2, 2] = 2
>>> index(arr1, 2)
(2, 2, 2)
>>> arr2 = np.ones(20)
>>> arr2[5] = 2
>>> index(arr2, 2)
(5,)
Esto puede ser mucho más rápido (porque está cortocircuitando la operación) que cualquier método que utilice np.where
o np.nonzero
.
Sin embargo, np.argwhere
también podría manejar con gracia arreglos multidimensionales (necesitaría convertirlo manualmente en una tupla y no está en cortocircuito) pero fallaría si no se encuentra una coincidencia:
>>> tuple(np.argwhere(arr1 == 2)[0])
(2, 2, 2)
>>> tuple(np.argwhere(arr2 == 2)[0])
(5,)
También puede convertir una matriz NumPy en una lista en el aire y obtener su índice. Por ejemplo,
l = [1,2,3,4,5] # Python list
a = numpy.array(l) # NumPy array
i = a.tolist().index(2) # i will return index of 2
print i
Se imprimirá 1.
Una alternativa a la selección del primer elemento de np.where () es usar una expresión generadora junto con enumerar, como:
>>> import numpy as np
>>> x = np.arange(100) # x = array([0, 1, 2, 3, ... 99])
>>> next(i for i, x_i in enumerate(x) if x_i == 2)
2
Para una matriz bidimensional uno haría:
>>> x = np.arange(100).reshape(10,10) # x = array([[0, 1, 2,... 9], [10,..19],])
>>> next((i,j) for i, x_i in enumerate(x)
... for j, x_ij in enumerate(x_i) if x_ij == 2)
(0, 2)
La ventaja de este enfoque es que deja de verificar los elementos de la matriz después de que se encuentra la primera coincidencia, mientras que np.where verifica la coincidencia de todos los elementos. Una expresión generadora sería más rápida si hubiera coincidencia al principio de la matriz.
l.index(x)
devuelve el i más pequeño, de modo que i es el índice de la primera aparición de x en la lista.
Se puede asumir con seguridad que la función index()
en Python se implementa de modo que se detenga después de encontrar la primera coincidencia, y esto se traduce en un rendimiento promedio óptimo.
Para encontrar un elemento que se detiene después de la primera coincidencia en una matriz NumPy use un iterador ( np.ndenumerate ).
In [67]: l=range(100)
In [68]: l.index(2)
Out[68]: 2
NumPy array:
In [69]: a = np.arange(100)
In [70]: next((idx for idx, val in np.ndenumerate(a) if val==2))
Out[70]: (2L,)
Tenga en cuenta que ambos métodos index()
y next
devuelven un error si no se encuentra el elemento. Con el next
, se puede usar un segundo argumento para devolver un valor especial en caso de que no se encuentre el elemento, por ejemplo
In [77]: next((idx for idx, val in np.ndenumerate(a) if val==400),None)
Existen otras funciones en NumPy ( argmax
, where
y nonzero
) que se pueden usar para encontrar un elemento en una matriz, pero todas tienen el inconveniente de recorrer toda la matriz en busca de todas las incidencias, por lo que no se optimizan para encontrar la primer elemento Tenga en cuenta también que where
y las matrices de retorno que nonzero
, por lo que debe seleccionar el primer elemento para obtener el índice.
In [71]: np.argmax(a==2)
Out[71]: 2
In [72]: np.where(a==2)
Out[72]: (array([2], dtype=int64),)
In [73]: np.nonzero(a==2)
Out[73]: (array([2], dtype=int64),)
Comparacion de tiempo
Simplemente comprobando que para arreglos grandes, la solución que usa un iterador es más rápida cuando el elemento buscado está al principio del arreglo (usando %timeit
en el shell de IPython):
In [285]: a = np.arange(100000)
In [286]: %timeit next((idx for idx, val in np.ndenumerate(a) if val==0))
100000 loops, best of 3: 17.6 µs per loop
In [287]: %timeit np.argmax(a==0)
1000 loops, best of 3: 254 µs per loop
In [288]: %timeit np.where(a==0)[0][0]
1000 loops, best of 3: 314 µs per loop
Este es un problema abierto de NumPy GitHub .
Ver también: Numpy: encuentra el primer índice de valor rápido
Nota: esto es para la versión de python 2.7
Puede usar una función lambda para resolver el problema, y funciona tanto en la lista NumPy como en la matriz.
your_list = [11, 22, 23, 44, 55]
result = filter(lambda x:your_list[x]>30, range(len(your_list)))
#result: [3, 4]
import numpy as np
your_numpy_array = np.array([11, 22, 23, 44, 55])
result = filter(lambda x:your_numpy_array [x]>30, range(len(your_list)))
#result: [3, 4]
Y puedes usar
result[0]
Para obtener el primer índice de los elementos filtrados.
Para Python 3.6, use
list(result)
en lugar de
result