我有一个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]])
答案 0 :(得分:6)
@Umang Gupta解决了您的问题。我很好奇这为什么起作用,所以我发布了我发现的其他上下文。 FWIW已经问过这个问题并回答了here,但是这个回答并没有真正按照我希望的方式遍历正在发生的一切,所以这是我的尝试:
使用*=
运算符会调用__imul__()
特殊方法来对Numpy ndarray进行就地乘法,这又calls是通用函数(ufunc)multiply()
。
multiply()
中有两个与这里相关的参数:out
和casting
。
out
参数指定输出(及其类型)。在就地乘法运算符中,out
设置为self
,即ndarray
对象,它称为乘法运算。特别是,*=
的{{3}}看起来像这样:
ufunc(self, other, out=(self,))
^其中ufunc = multiply
,self = b
(ndarray
,键入int64
和other = 2.1
(标量,键入float
)
然而,casting
参数确定操作所允许的数据类型强制转换的规则。 the exact call,casting
的默认值为same_kind
,As 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
有效。