python - objects - Acceda a mĂșltiples elementos de una matriz
mongodb subdocument query (3)
Puedes usar np.choose
.
Aquí hay un ejemplo de Array NumPy:
array([[ 0, 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12, 13],
[14, 15, 16, 17, 18, 19, 20]])
Digamos que queremos elegir los valores [1, 2, 3]
de la primera fila, [11, 12, 13]
de la segunda fila y [17, 18, 19]
de la tercera fila.
En otras palabras, seleccionaremos los índices de cada fila de arr
como se muestra en una matriz idx
:
array([[1, 2, 3],
[4, 5, 6],
[3, 4, 5]])
Luego usando np.choose
:
>>> np.choose(idx, arr.T[:,:,np.newaxis])
array([[ 1, 2, 3],
[11, 12, 13],
[17, 18, 19]])
Para explicar lo que acaba de suceder: arr.T[:,:,np.newaxis]
significaba que arr
se veía temporalmente como una matriz 3D con forma (7, 3, 1)
. Puedes imaginar esto como una matriz 3D donde cada columna del arr
original ahora es un vector de columna 2D con tres valores. La matriz 3D se parece un poco a esto:
# 0 1 2 3 4 5 6
[[ 0] [[ 1] [[ 2] [[ 3] [[ 4] [[ 5] [[ 6] # choose values from 1, 2, 3
[ 7] [ 8] [ 9] [10] [11] [12] [13] # choose values from 4, 5, 6
[14]] [15]] [16]] [17]] [18]] [19]] [20]] # choose values from 3, 4, 5
Para obtener la fila zeroth de la matriz de salida, seleccione selecciona el elemento zeroth de la columna 2D en el índice 1
, el elemento zeroth de la columna 2D en el índice 2
y el elemento zeroth de la columna 2D en el índice 3
.
Para obtener la primera fila de la matriz de salida, seleccione selecciona el primer elemento de la columna 2D en el índice 4
, el primer elemento de la columna 2D en el índice 5
, ... y así sucesivamente.
¿Hay alguna forma de obtener elementos de matriz en una operación para filas y columnas conocidas de esos elementos? En cada fila me gustaría acceder a los elementos de col_start a col_end (cada fila tiene diferentes índices de inicio y finalización). El número de elementos es el mismo para cada fila, los elementos son consecutivos. Ejemplo:
[ . . . . | | | . . . . . ]
[ | | | . . . . . . . . . ]
[ . . | | | . . . . . . . ]
[ . . . . . . . . | | | . ]
Una solución sería obtener índices (par fila-columna) de elementos y utilizar my_array [row_list, col_list].
¿Hay alguna otra forma (más simple) sin usar para los bucles?
Creo que estás buscando algo como lo siguiente. Sin embargo, no estoy seguro de qué quieres hacer con ellos cuando accedes a ellos.
indexes = [(4,6), (0,2), (2,4), (8, 10)]
arr = [
[ . . . . | | | . . . . . ],
[ | | | . . . . . . . . . ],
[ . . | | | . . . . . . . ],
[ . . . . . . . . | | | . ]
]
for x in zip(indexes, arr):
index = x[0]
row = x[1]
print row[index[0]:index[1]+1]
A = np.arange(40).reshape(4,10)*.1
startend = [[2,5],[3,6],[4,7],[5,8]]
index_list = [np.arange(v[0],v[1]) + i*A.shape[1]
for i,v in enumerate(startend)]
# [array([2, 3, 4]), array([13, 14, 15]), array([24, 25, 26]), array([35, 36, 37])]
A.flat[index_list]
productor
array([[ 0.2, 0.3, 0.4],
[ 1.3, 1.4, 1.5],
[ 2.4, 2.5, 2.6],
[ 3.5, 3.6, 3.7]])
Esto todavía tiene una iteración, pero es bastante básico sobre una lista. Estoy indexando la versión plana, 1d, de A
np.take(A, index_list)
también funciona.
Si los intervalos de fila difieren en tamaño, puedo usar np.r_
para concatenarlos. No es absolutamente necesario, pero es una ventaja cuando se crean índices a partir de múltiples intervalos y valores.
A.flat[np.r_[tuple(index_list)]]
# array([ 0.2, 0.3, 0.4, 1.3, 1.4, 1.5, 2.4, 2.5, 2.6, 3.5, 3.6, 3.7])
El idx
que usa el ajcr
se puede usar sin choose
:
idx = [np.arange(v[0], v[1]) for i,v in enumerate(startend)]
A[np.arange(A.shape[0])[:,None], idx]
idx
es como mi index_list
excepto que no agrega la longitud de la fila.
np.array(idx)
array([[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7]])
Como cada arange
tiene la misma longitud, idx
se puede generar sin iteración:
col_start = np.array([2,3,4,5])
idx = col_start[:,None] + np.arange(3)
El primer índice es una matriz de columnas que difunde para que coincida con este idx
.
np.arange(A.shape[0])[:,None]
array([[0],
[1],
[2],
[3]])
Con esta A
e idx
obtengo los siguientes tiempos:
In [515]: timeit np.choose(idx,A.T[:,:,None])
10000 loops, best of 3: 30.8 µs per loop
In [516]: timeit A[np.arange(A.shape[0])[:,None],idx]
100000 loops, best of 3: 10.8 µs per loop
In [517]: timeit A.flat[idx+np.arange(A.shape[0])[:,None]*A.shape[1]]
10000 loops, best of 3: 24.9 µs per loop
La indexación flat
es más rápida, pero calcular el índice más sofisticado toma algo de tiempo.
Para arreglos grandes, domina la velocidad de indexación flat
.
A=np.arange(4000).reshape(40,100)*.1
col_start=np.arange(20,60)
idx=col_start[:,None]+np.arange(30)
In [536]: timeit A[np.arange(A.shape[0])[:,None],idx]
10000 loops, best of 3: 108 µs per loop
In [537]: timeit A.flat[idx+np.arange(A.shape[0])[:,None]*A.shape[1]]
10000 loops, best of 3: 59.4 µs per loop
El método np.choose
se ejecuta en un límite codificado: Need between 2 and (32) array objects (inclusive).
¿Qué fuera de límites idx
?
col_start=np.array([2,4,6,8])
idx=col_start[:,None]+np.arange(3)
A[np.arange(A.shape[0])[:,None], idx]
produce un error porque el último valor de idx
es 10
, demasiado grande.
Puede clip
idx
idx=idx.clip(0,A.shape[1]-1)
produciendo valores duplicados en la última fila
[ 3.8, 3.9, 3.9]
También puede rellenar A
antes de indexar. Ver np.pad
para más opciones.
np.pad(A,((0,0),(0,2)),''edge'')[np.arange(A.shape[0])[:,None], idx]
Otra opción es eliminar los valores fuera de límites. idx
se convertiría en una lista desigual de listas (o una matriz de listas). El enfoque flat
puede manejar esto, aunque el resultado no será una matriz.
startend = [[2,5],[4,7],[6,9],[8,10]]
index_list = [np.arange(v[0],v[1]) + i*A.shape[1]
for i,v in enumerate(startend)]
# [array([2, 3, 4]), array([14, 15, 16]), array([26, 27, 28]), array([38, 39])]
A.flat[np.r_[tuple(index_list)]]
# array([ 0.2, 0.3, 0.4, 1.4, 1.5, 1.6, 2.6, 2.7, 2.8, 3.8, 3.9])