如何将 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()
中有两个与此处相关的参数:out
和 casting
。
out
参数指定输出(及其类型)。在就地乘法运算符中,out
设置为self
,即调用乘法运算的ndarray
对象。特别是,the exact call for *=
看起来像这样:
ufunc(self, other, out=(self,))
^ 其中ufunc = multiply
、self = b
(ndarray
,键入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 数组转换为张量(不支持的对象类型浮点数)