Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with true division with Numpy arrays

Suppose you have this array:

In [29]: a = array([[10, 20, 30, 40, 50], [14, 28, 42, 56, 70], [18, 36, 54, 72, 90]])

Out[30]: a
array([[ 0,  0,  0,  0,  0],
       [14, 28, 42, 56, 70],
       [18, 36, 54, 72, 90]])

Now divide the third row by the first one (using from future import division)

In [32]: a[0]/a[2]
Out[32]: array([ 0.55555556,  0.55555556,  0.55555556,  0.55555556,  0.55555556])

Now do the same with each row in a loop:

In [33]: for i in range(3):
            print a[i]/a[2]   
[ 0.55555556  0.55555556  0.55555556  0.55555556  0.55555556]
[ 0.77777778  0.77777778  0.77777778  0.77777778  0.77777778]
[ 1.  1.  1.  1.  1.]

Everything looks right. But now, assign the first array a[i]/a[2] to a[i]:

In [35]: for i in range(3):
            a[i]/=a[2]
   ....:     

In [36]: a
Out[36]: 
array([[0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1]])

Alright, no problem. Turns out this is by design. Instead, we should do:

In [38]: for i in range(3):
            a[i] = a[i]/a[2]
   ....:     

In [39]: a
Out[39]: 
array([[0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1]])

But that doesn't work. Why and how can I fix it?

Thanks in advance.

like image 929
Robert Smith Avatar asked Dec 10 '25 15:12

Robert Smith


2 Answers

You can cast the whole array to a float array first:

a = a.astype('float')
a /= a[2]
like image 142
nneonneo Avatar answered Dec 12 '25 05:12

nneonneo


"Why doesn't this work" -- The reason it doesn't work is because numpy arrays have a datatype when they're created. Any attempt to put a different type into that array will be cast to the appropriate type. In other words, when you try to put a float into your integer array, numpy casts the float to an int. The reasoning behind this is because numpy arrays are designed to be a homogonous type in order for them to have optimal performance. Put another way, they're implemented as arrays in C. And in C, you can't have an array where 1 element is a float and the next is an int. (You can have structs which behave like that, but they're not arrays).

Another solution (in addition to the one proposed by @nneonneo) is to specify the array as a float array from the beginning:

a = array([[10, 20, 30, 40, 50], [14, 28, 42, 56, 70], [18, 36, 54, 72, 90]], dtype=float)
like image 30
mgilson Avatar answered Dec 12 '25 06:12

mgilson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!