如何将 int numpy 数组的列乘以浮点数并保持在 int 中?

Posted

技术标签:

【中文标题】如何将 int numpy 数组的列乘以浮点数并保持在 int 中?【英文标题】:How can I multiply column of the int numpy array to the float digit and stays in int? 【发布时间】:2018-07-22 15:54:16 【问题描述】:

我有一个 numpy 数组:

 >>> b
 array([[ 2,  2],
        [ 6,  4],
        [10,  6]])

我想将第一列乘以浮点数,结果我需要整数,因为当我这样做时:

>>> b[:,0] *= 2.1

上面写着:

TypeError: Cannot cast ufunc multiply output from dtype('float64') to dtype('int64') with casting rule 'same_kind'

我需要这样的数组:

array([[ 4,  2],
       [12,  4],
       [21,  6]])

【问题讨论】:

b[:,0] = b[:,0]*2.1 哇,为什么会这样? 并转换为 int :(b[:,0]*2.1).astype(int) @AntonvBR 不需要投射。 显然*= 比普通= 有更严格的转换规则, 【参考方案1】:

@Umang Gupta 为您的问题提供了解决方案。我很好奇自己为什么会这样,所以我将我发现的内容发布为额外的上下文。 FWIW 这个问题已经被问到并回答了here,但这个答案也并没有像我希望的那样真正了解正在发生的事情,所以这是我的尝试:

使用*= 运算符调用__imul__() 特殊方法用于Numpy ndarrays 的就地乘法,这反过来又calls 通用函数(ufunc)multiply()

multiply() 中有两个与此处相关的参数:outcasting

out 参数指定输出(及其类型)。在就地乘法运算符中,out 设置为self,即调用乘法运算的ndarray 对象。特别是,the exact call for *= 看起来像这样:

ufunc(self, other, out=(self,))

^ 其中ufunc = multiplyself = bndarray,键入int64,和other = 2.1(标量,键入float

然而,casting 参数决定了作为操作结果允许进行何种数据类型转换的规则。 As of Numpy 1.10,casting的默认值为same_kind,which means:

只允许安全强制转换或类型中的强制转换,如 float64 到 float32

由于我们的 ufunc 调用没有为 casting 参数指定值,因此使用默认值 (same_kind) - 但这会导致问题,因为我们已经指定了 out具有int64 dtype,它与 int-by-float 乘法的输出相同。使用same_kind 强制转换,操作的float 结果无法转换为int。这就是我们看到这个错误的原因。

我们可以使用multiply() 显式复制此错误:

np.multiply(b, 2.1, out=b)
TypeError: Cannot cast ufunc multiply output from dtype('float64') to dtype('int64') with casting rule 'same_kind'  

可以通过将参数值设置为"unsafe" 来放宽multiply()casting 要求。然后,当out也被设置时,输出被强制为out的类型,不管它是否相同(如果可能的话):

np.multiply(b, 2.1, out=b, casting="unsafe")
# specifying int output and allowing casting to be "unsafe" allows re-conversion to int
array([[ 4,  4],
       [12,  8],
       [21, 12]])

另一方面,使用普通赋值运算符更新b[:,0] 是可以的。这就是@Umang Gupta 的解决方案所做的。 与:

b[:,0] = b[:,0]* 2.1

* 调用multiply ufunc,就像*= 一样。但由于它没有调用操作的就地版本,因此没有指定 out 参数,因此没有设置输出类型。然后,标准类型转换允许整数向上转换为浮点数:

np.multiply(b, 2.1)
# float output
array([[  4.2,   4.2],
       [ 12.6,   8.4],
       [ 21. ,  12.6]])

然后普通赋值运算符= 获取乘法的输出并将其存储在b[:,0] 中。根据 the Numpy docs 将值分配给索引数组:

请注意,如果将较高的类型分配给较低的类型(例如将浮点数分配给整数),则分配可能会导致更改

所以问题在于*= 运算符自动设置out 参数,而没有将casting 参数从same_kind 更改为unsafe。 (并不是说这是一个错误,只是这就是您收到错误的原因。)并且公认的解决方案通过利用 Numpy 中分配的自动“向下转换”属性来解决这个问题。希望有帮助! (另外,Numpy 专业人士,请随时纠正我的任何误解。)

【讨论】:

感谢您的解释:) 优秀的答案【参考方案2】:

虽然b[:,0] *= 2.1 可能不起作用,但b[:,0] = b[:,0]* 2.1 起作用。

【讨论】:

以上是关于如何将 int numpy 数组的列乘以浮点数并保持在 int 中?的主要内容,如果未能解决你的问题,请参考以下文章

Tensorflow - ValueError:无法将 NumPy 数组转换为张量(不支持的对象类型浮点数)

将 CSV 文件读取到 numpy 数组,第一行为字符串,其余为浮点数

如何将浮点数转换为长度为 4 的字节数组(char* 数组)?

无法将 NumPy 数组转换为张量(不支持的对象类型浮点数)

尝试连接 keras 模型:ValueError:无法将 NumPy 数组转换为张量(不支持的对象类型浮点数)

如何在 CMTimeMake 的时间刻度 Int32 中传递浮点数