Heinz Heinz - 1 month ago 10
Python Question

python: If loop returns wrong result

I wrote the following script trying to calculate portions in array a and stack the result to the original array:

import numpy


a = numpy.array([[1, 4, 4.555],
[2, 3, 9.112],
[3, 1, 7.322],
[1, 5, 3.911]])

i = 0
b = numpy.ones((4,1))
if i <= 2:
b[i][0] = float(a[i][2])/(a[i][2]+a[i+1][2])
b[i+1][0] = float(a[i+1][2])/(a[i][2]+a[i+1][2])
i = i+2
print b
c = numpy.hstack((a,b))
print c


But the result were strange:

array b:
[[ 0.33328455]
[ 0.66671545]
[ 1. ]
[ 1. ]]
array c:
[[ 1. 4. 4.555 0.33328455]
[ 2. 3. 9.112 0.66671545]
[ 3. 1. 7.322 1. ]
[ 1. 5. 3.911 1. ]]


The first and second rows of array c was what I want, but the rest rows were strange. The result array I expected is:

[[ 1. 4. 4.555 0.33328455]
[ 2. 3. 9.112 0.66671545]
[ 3. 1. 7.322 0.65182943]
[ 1. 5. 3.911 0.34817057]]


How to fix this? And is there more efficient coding to do this task?

Answer

There is no such thing as an if loop. An if statement will execute a block if the test matches, but will only execute it once. Your i = i+2 statement at the end of the block won't cause the code to be repeated.

You probably wanted a while loop there:

while i <= 2:
    b[i][0] = float(a[i][2]) / (a[i][2] + a[i+1][2])
    b[i+1][0] = float(a[i+1][2]) / (a[i][2] + a[i+1][2])
    i += 2

while repeatedly executes the block as long as the test is true.

You could use a for loop too, with an xrange() object that increments in steps of 2:

for i in xrange(0, len(b), 2):
    b[i][0] = float(a[i][2]) / (a[i][2] + a[i+1][2])
    b[i+1][0] = float(a[i+1][2]) / (a[i][2] + a[i+1][2])

Either way, by looping the expected output is produced:

[[ 1.          4.          4.555       0.33328455]
 [ 2.          3.          9.112       0.66671545]
 [ 3.          1.          7.322       0.65182943]
 [ 1.          5.          3.911       0.34817057]]