Reputation: 249153
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])
As a C and C++ programmer I can understand why this happens (it's memcpy() instead of memmove() all over again), but it seems like end users of Python and NumPy might not expect this. And I failed to find any documentation saying this wouldn't work.
The question is: is there a bug in NumPy here (probably not), or is there some NumPy documentation explaining what the rules are in situations like this, or is that missing from the documentation?
Secondly, I would like to figure out a safe, working solution which is quasi-optimal in space and time. That is, it should not allocate memory beyond a constant amount, and it should not be a silly pure-Python "for" loop. :) Those are the goals one might hope to achieve with the in-place modification which clearly doesn't work.
I'm using NumPy 1.8.0.
Upvotes: 4
Views: 120
Reputation: 323
Im posting here again to correct my answer. perhaps try:
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])
sorry miss-understood the question before,
the reason for the result:
'array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5])'
is
that this action is actually syntaxed as the deduction of
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]
I think what you really want is above
tnx EdChum
Upvotes: 1
Reputation: 249153
I did find some discussion after posting this question. The important term to search for is "slice". It's here: http://numpy-discussion.10968.n7.nabble.com/Strange-behavior-in-setting-masked-array-values-in-Numpy-1-1-0-td11999.html
Partway down the page there is discussion about trying to detect and warn about this sort of thing, but it sounds like a lost cause. So I set about finding another in-place method to do what I wanted. Here it is!
bc[-1:0:-1] -= bc[-2::-1]
Credit to @fredtantini for explicitly writing out the pure-Python "for" loop which NumPy effectively does. That got me thinking about how to fix it in pure Python (iterate backward!), which led to the above solution.
Upvotes: 0
Reputation: 16556
I don't think that's a bug:
Doing bc[1:] -= bc[:-1]
you are modifying the list while doing the operations.
The process is like
for i in range(1,len(bc)):
bc[i] = bc[i] - bc[i-1]
So the next step bc[i-1]
is modified:
"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,…
And so on so forth.
For the rest of the question, I can't answer.
Upvotes: 0