根据规则“安全”,无法将数组数据从dtype('float64')转换为dtype('int32')

时间:2018-08-07 19:49:15

标签: python numpy

我有一个像

这样的numpy数组
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]]])

如果元素大于255,我将尝试屏蔽该数组。即,我假定其范围为0-1024,并将我的值除以4

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

注意:结果是先前的3D阵列。我收到此错误

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

我在做什么错? 预先感谢

2 个答案:

答案 0 :(得分:2)

错误说明:

这说明了numpy数组的一个有趣属性: numpy数组的所有元素必须具有相同的类型

例如,如果您具有以下数组:

>>> 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'>

我们注意到,即使列表[23,632,634]中的所有元素都是 int 类型(特别是'numpy.int64'),由于第二行中的元素 123.6 array1 中的所有元素都转换为浮点数(请注意打印出数组中的小数点)。

简单地说,如果我们在数组的任何位置甚至包含一个字符串,那么数组的所有元素都将转换为字符串:

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

结论:

您原始的 result 数组包含'numpy.int64'类型的元素,但是result/4操作返回一个'类型的元素数组numpy.float64'(因为 82/4 = 20.5 等)。因此,当您尝试替换 result 中的值时,这是不安全的,因为您无意中试图将浮点数放入一个整数数组中。

答案 1 :(得分:1)

问题是当您除以4时,您正在创建浮点值,这些浮点值不希望进入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]]])

替代#1:

将您的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]]])

如果需要,甚至可以转换回int:

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]]])

替代2:

完全取消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]]])