Tal vez se ha preguntado antes, pero no puedo encontrarlo. A veces tengo un índice I, y quiero agregar sucesivamente de acuerdo con este índice a una matriz numpy, desde otra matriz. Por ejemplo:
A = np.array([1,2,3]) B = np.array([10,20,30]) I = np.array([0,1,1]) for i in range(len(I)): A[I[i]] += B[i] print(A)imprime el valor esperado (correcto):
[11 52 3]mientras
A[I] += B print(A)da como resultado la respuesta esperada (incorrecta)
[11 32 3].¿Hay alguna forma de hacer lo que quiero de forma vectorizada, sin el bucle? Si no, ¿cuál es la forma más rápida de hacer esto?
Utilice numpy.add.at :
>>> import numpy as np >>> A = np.array([1,2,3]) >>> B = np.array([10,20,30]) >>> I = np.array([0,1,1]) >>> >>> np.add.at(A, I, B) >>> A array([11, 52, 3]) Alternativamente, np.bincount :
>>> A = np.array([1,2,3]) >>> B = np.array([10,20,30]) >>> I = np.array([0,1,1]) >>> >>> A += np.bincount(I, B, minlength=A.size).astype(int) >>> A array([11, 52, 3])¿Cual es mas rápido?
Depende En este ejemplo concreto, add.at parece marginalmente más rápido, presumiblemente porque necesitamos convertir tipos en la solución bincount .
Si OTOH A y B fueran de tipo float , bincount sería más rápido.
Necesitas usarnp.add.at :
A = np.array([1,2,3]) B = np.array([10,20,30]) I = np.array([0,1,1]) np.add.at(A, I, B) print(A)huellas dactilares
array([11, 52, 3])Esto se nota en el documento:
ufunc.at(a, índices, b=Ninguno)
Realiza una operación in situ sin búfer en el operando 'a' para los elementos especificados por 'índices'. Para suma ufunc, este método es equivalente a a[índices] += b, excepto que los resultados se acumulan para los elementos que se indexan más de una vez. Por ejemplo, a[[0,0]] += 1 solo incrementará el primer elemento una vez debido al almacenamiento en búfer, mientras que add.at(a, [0,0], 1) incrementará el primer elemento dos veces.