如何将int numpy数组的列乘以float数字并保持int?

kar*_*baq 3 python numpy

我有一个numpy数组:

 >>> b
 array([[ 2,  2],
        [ 6,  4],
        [10,  6]])
Run Code Online (Sandbox Code Playgroud)

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

>>> b[:,0] *= 2.1
Run Code Online (Sandbox Code Playgroud)

它说:

TypeError: Cannot cast ufunc multiply output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
Run Code Online (Sandbox Code Playgroud)

我需要看起来像这样的数组:

array([[ 4,  2],
       [12,  4],
       [21,  6]])
Run Code Online (Sandbox Code Playgroud)

and*_*ece 6

@Umang Gupta解决了你的问题.我很好奇为什么这个有用,所以我发布了我发现的附加上下文.FWIW这个问题已经在这里被问到并回答,但是这个答案也没有像我希望的那样真正地了解正在发生的事情,所以这是我的尝试:

使用*=运算符调用__imul__()Numpy ndarrays的就地乘法的特殊方法,后者又调用通用函数(ufunc)multiply().

这里有两个multiply()相关的参数:outcasting.

所述out参数指定的输出(与它的类型一起).在就地乘法运算符中,out设置为self,即ndarray调用乘法运算的对象.特别是,确切的调用*=这个样子的:

ufunc(self, other, out=(self,))
Run Code Online (Sandbox Code Playgroud)

^ where ufunc = multiply,self = b(ndarray,type int64,and other = 2.1(scalar,type float)

casting但是,该参数确定了由于操作而允许哪种数据类型转换的规则. 从Numpy 1.10开始,默认值为castingis same_kind,表示:

只允许使用float64到float32之类的安全转换或类型转换

由于我们的ufunc电话没有指定的值casting参数,默认值(same_kind)用于-但因为我们这会导致问题已经指定out为具有int64D型细胞,这是不是同一种与int-通过流通倍增的输出.使用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'  
Run Code Online (Sandbox Code Playgroud)

通过设置参数值可以放宽casting要求.然后,当设置时,输出被强制转换为类型,无论它是否相同(如果可能):multiply()"unsafe"outout

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]])
Run Code Online (Sandbox Code Playgroud)

b[:,0]另一方面,使用常规赋值运算符进行更新是可以的.这就是@Umang Gupta的解决方案.
附:

b[:,0] = b[:,0]* 2.1
Run Code Online (Sandbox Code Playgroud)

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

np.multiply(b, 2.1)
# float output
array([[  4.2,   4.2],
       [ 12.6,   8.4],
       [ 21. ,  12.6]])
Run Code Online (Sandbox Code Playgroud)

然后,正常赋值运算符=获取乘法的输出并将其存储b[:,0].根据Numpy文档为索引数组赋值:

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

所以,问题的关键在于*=运营商的自动的设定out参数不改变casting从论证same_kindunsafe.(并不是说这是一个错误,只是因为这就是你得到错误的原因.)并且通过利用Numpy中赋值的自动"向下转换"属性,接受的解决方案可以解决这个问题.希望有所帮助!(另外,Numpy专业人士,请随时纠正我的任何误解.)


Uma*_*pta 3

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