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

时间:2018-07-22 15:54:16

标签: python numpy

我有一个numpy数组:

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

我想将第一列乘以浮点数,因此我需要int数,因为这样做的时候:

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

2 个答案:

答案 0 :(得分:6)

@Umang Gupta解决了您的问题。我很好奇这为什么起作用,所以我发布了我发现的其他上下文。 FWIW已经问过这个问题并回答了here,但是这个回答并没有真正按照我希望的方式遍历正在发生的一切,所以这是我的尝试:

使用*=运算符会调用__imul__()特殊方法来对Numpy ndarray进行就地乘法,这又calls是通用函数(ufunc)multiply()

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

out参数指定输出(及其类型)。在就地乘法运算符中,out设置为self,即ndarray对象,它称为乘法运算。特别是,*=的{​​{3}}看起来像这样:

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

^其中ufunc = multiplyself = bndarray,键入int64other = 2.1(标量,键入float

然而,casting参数确定操作所允许的数据类型强制转换的规则。 the exact callcasting的默认值为same_kindAs of Numpy 1.10

  

仅允许安全类型转换或同一类型(例如float64到float32)内的类型转换

由于我们的ufunc调用未为casting参数指定值,所以使用了默认值(same_kind)-但这会引起问题,因为我们拥有out指定为具有int64 dtype,这与int-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'  

通过将参数值设置为casting,可以放宽multiply()的{​​{1}}要求。然后,如果还设置了"unsafe",则输出将强制为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]]) 。这就是@Umang Gupta的解决方案。
使用:

b[:,0]

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

out

然后,普通赋值运算符np.multiply(b, 2.1) # float output array([[ 4.2, 4.2], [ 12.6, 8.4], [ 21. , 12.6]]) 获取乘法的输出并将其存储在=中。根据{{​​3}},将值分配给索引数组:

  

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

因此,问题出在b[:,0]操作符对*=参数的自动设置而没有将out参数从casting更改为same_kind。 (并不是这是一个错误,只是这就是为什么您会遇到错误。)并且公认的解决方案通过利用Numpy中分配的自动“向下转换”属性来解决此问题。希望有帮助! (此外,Numpy的专业人士,请随时纠正我的任何误解。)

答案 1 :(得分:1)

虽然b[:,0] *= 2.1无效,但b[:,0] = b[:,0]* 2.1有效。