Cannot cast array data from dtype('float64') to dtype('int32') according to the rule 'safe'

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



Cannot cast array data from dtype('float64') to dtype('int32') according to the rule 'safe'



I have a numpy array like


result = np.array([[[289, 354, 331],
[291, 206, 66],
[242, 70, 256]],

[[210, 389, 342],
[273, 454, 218],
[255, 87, 256]],

[[127, 342, 173],
[450, 395, 147],
[223, 228, 401]]])



and i'm trying to mask the array if an element is greater than 255. i.e i assume it to be of range 0-1024 and divide my value by 4


result = np.putmask(result, result > 255, result/4)



NOTE: result is the previous 3D array.And i'm getting this error


TypeError: Cannot cast array data from dtype('float64') to dtype('int32') according to the rule 'safe'



What am i doing wrong?
Thanks in advance




2 Answers
2



Explanation of Error:



This is illustrative of an interesting property of numpy arrays: all elements of a numpy array must be of the same type



For instance if you have the following array:


>>> array1 = np.array([[23, 632, 634],[23.5, 67, 123.6]])
>>> array1
array([[ 23. , 632. , 634. ],
[ 23.5, 67. , 123.6]])
>>> type(array1[0][0])
<class 'numpy.float64'>



We notice that even though all the elements in the list [23, 632, 634] were all of the type int (specifically 'numpy.int64'), all of the elements in array1 were converted to floats because of the element 123.6 in the second row (notice the decimal points in the array print out).



Similarily, if we include even one string anywhere in the array, all the elements of the array are cast to strings:


>>> array2 = np.array([[23, 632, 'foo'],[23.5, 67, 123.6]])
>>> type(array2[0][0])
<class 'numpy.str_'>



Conclusion:



Your original result array contains elements of type 'numpy.int64', but the result/4 operation returns an array of elements of type 'numpy.float64' (since 82 / 4 = 20.5, etc.). Thus when you try and replace the values in result, it is not 'safe' as you are inadvertently trying to place floats into an array of ints.


result/4





Nice description of the problem! +1
– sacul
Aug 7 at 20:31





Many thanks for the description
– Anantha Ramakrishnan
Aug 8 at 3:47





No problem guys, great question!
– Yang T
Aug 8 at 3:57



The problem is that when you divide by 4, you are creating float values, which don't want to go into the array of ints.


int



If you want to use putmask, and avoid the problem of trying to convert to float, then you can use floor division (//) in order to change your values to int:


putmask


//


int


np.putmask(result, result>255, result//4)

>>> result
array([[[ 72, 88, 82],
[ 72, 206, 66],
[242, 70, 64]],

[[210, 97, 85],
[ 68, 113, 218],
[255, 87, 64]],

[[127, 85, 173],
[112, 98, 147],
[223, 228, 100]]])



Alternative #1:



Convert your result array to a float dtype, and use your original putmask:


result


dtype


putmask


result = result.astype(float)

np.putmask(result, result > 255, result/4)

>>> result
array([[[ 72.25, 88.5 , 82.75],
[ 72.75, 206. , 66. ],
[242. , 70. , 64. ]],

[[210. , 97.25, 85.5 ],
[ 68.25, 113.5 , 218. ],
[255. , 87. , 64. ]],

[[127. , 85.5 , 173. ],
[112.5 , 98.75, 147. ],
[223. , 228. , 100.25]]])



You can even convert back to int after if desired:


result = result.astype(int)

array([[[ 72, 88, 82],
[ 72, 206, 66],
[242, 70, 64]],

[[210, 97, 85],
[ 68, 113, 218],
[255, 87, 64]],

[[127, 85, 173],
[112, 98, 147],
[223, 228, 100]]])



Alternative #2:



Do away with putmask altogether, and you can get your desired results like this:


putmask


result[result > 255] = result[result > 255] / 4

>>> result
array([[[ 72, 88, 82],
[ 72, 206, 66],
[242, 70, 64]],

[[210, 97, 85],
[ 68, 113, 218],
[255, 87, 64]],

[[127, 85, 173],
[112, 98, 147],
[223, 228, 100]]])





Yep. That worked thanks. But any way how to solve the problem I had?
– Anantha Ramakrishnan
Aug 7 at 20:03





See the first method I suggested (in my edited post), I tried to explain what was happening.
– sacul
Aug 7 at 20:04






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

Creating a leaderboard in HTML/JS