import numpy as np
bc = np.arange(10) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# regular way using NumPy function
np.diff(bc) # array([1, 1, 1, 1, 1, 1, 1, 1, 1])

# something similar with array subtraction:
bc[1:] - bc[:-1] # array([1, 1, 1, 1, 1, 1, 1, 1, 1])

# but this does the wrong thing:
bc[1:] -= bc[:-1] # array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5])

Como programador en C y C ++, puedo entender por qué sucede esto (es memcpy () en lugar de memmove () de nuevo), pero parece que los usuarios finales de Python y NumPy podrían no esperar esto. Y no pude encontrar ninguna documentación que dijera que esto no funcionaría.

La pregunta es: ¿hay un error en NumPy aquí (probablemente no), o hay alguna documentación de NumPy que explique cuáles son las reglas en situaciones como esta, o falta en la documentación?

En segundo lugar, me gustaría encontrar una solución segura y funcional que sea casi óptima en el espacio y el tiempo. Es decir, no debe asignar memoria más allá de una cantidad constante, y no debe ser un bucle "for" tonto de Python puro. :) Esos son los objetivos que uno podría esperar lograr con la modificación en el lugar que claramente no funciona.

Estoy usando NumPy 1.8.0.

3
John Zwinck 4 sep. 2014 a las 12:29

3 respuestas

La mejor respuesta

Encontré alguna discusión después de publicar esta pregunta. El término importante para buscar es "corte". Está aquí: http://numpy-discussion.10968.n7.nabble.com/Strange-behavior-in-setting-masked-array-values-in-Numpy-1-1-0-td11999 .html

A mitad de la página hay una discusión sobre tratar de detectar y advertir sobre este tipo de cosas, pero parece una causa perdida. Así que me puse a buscar otro método in situ para hacer lo que quería. ¡Aquí está!

bc[-1:0:-1] -= bc[-2::-1]

Gracias a @fredtantini por escribir explícitamente el bucle "for" de Python puro que NumPy efectivamente hace. Eso me hizo pensar en cómo solucionarlo en Python puro (¡iterar hacia atrás!), Lo que condujo a la solución anterior.

0
Community 23 may. 2017 a las 11:57

No creo que sea un error:
Haciendo bc[1:] -= bc[:-1] estás modificando la lista mientras haces las operaciones.

El proceso es como

for i in range(1,len(bc)):
    bc[i] = bc[i] - bc[i-1]

Entonces, el siguiente paso bc[i-1] se modifica:

"i"      1
bc[1:]:  1,2,3,4,5,…
bc[:-1]: 0,1,2,3,4,5,… 
bc[1]= 1 - 0 = 1
new bc: 0,1,2,3,4,5,…

"i"        2
bc[1:]:  1,2,3,4,5,…
bc[:-1]: 0,1,2,3,4,5,… 
bc[2]= 2 - 1 = 1
new bc: 0,1,1,3,4,5,…


"i"          3
bc[1:]:  1,1,3,4,5,…
bc[:-1]: 0,1,1,3,4,5,… 
bc[1]= 3 - 1 = 2
new bc: 0,1,1,2,4,5,…


"i"            4
bc[1:]:  1,1,2,4,5,…
bc[:-1]: 0,1,1,2,4,5,… 
bc[1]= 4 - 2 = 2
new bc: 0,1,1,2,2,5,…

Y así sucesivamente.

Para el resto de la pregunta, no puedo responder.

0
fredtantini 4 sep. 2014 a las 09:01

Estoy publicando aquí nuevamente para corregir mi respuesta. tal vez intente:

bc-=np.roll( bc , 1 )

#array([-9,  1,  1,  1,  1,  1,  1,  1,  1,  1])
#this arrays length is 10

#and then for an array with length 9
bc=bc[ 1 : ]  

#array([1,  1,  1,  1,  1,  1,  1,  1,  1])

Lo siento, no entendí la pregunta antes,

La razón del resultado:

'array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5])'

Es

Que esta acción está realmente sintaxis como la deducción de

let (say...) a=array([0,1,2,3,4,5,6,7,8,9])
updated a <- will be formed as [0, 1-0=1,2-1=1,3-1=2,4-2=2,5-2=3,6-3=3,7-3=4,8-4=4,9-4=5] 

Creo que lo que realmente quieres está arriba

Tnx EdChum

1
hpaulj 4 sep. 2014 a las 21:29