为啥numpy数组的astype方法在转换类型时不修改输入?

Posted

技术标签:

【中文标题】为啥numpy数组的astype方法在转换类型时不修改输入?【英文标题】:Why does numpy array's astype method not modify the input when casting type?为什么numpy数组的astype方法在转换类型时不修改输入? 【发布时间】:2016-02-04 17:29:48 【问题描述】:

我正在使用 numpy 的数组对象的 astype 方法将数组从字符转换为整数。为了效率,我使用了copy=False,但我注意到原来的数组实际上并没有被修改。如果不将 b 声明为新数组,这怎么可能?

import numpy

a=numpy.array(['0','1']) 
b=a.astype(numpy.int32,copy=False)
print a[0], b[0]

【问题讨论】:

比较 a.nbytesb.nbytes。一个是 2,另一个是 8。你和 numpy 不能将 2 个 4byte 整数压缩到 2 个 1byte 字符槽中。 【参考方案1】:

这里有两个明显的问题。一、

numpy.array(a)

b=numpy.array(a).astype(numpy.int32,copy=False)

已经制作了副本。二、来自docs:

如果[复制参数]设置为false,满足dtype、ordersubok要求,输入数组返回而不是副本。

NumPy 只是忽略了copy=False,因为 dtype 不匹配意味着它需要复制。

【讨论】:

对,将 numpy.array(a) 视为一个巨大的错字:)【参考方案2】:

从docs,只有在以下情况下才会避免复制,

复制:布尔值,可选

默认情况下,astype 总是返回一个新分配的数组。如果设置为 false,并且满足 dtype、order 和 subok 要求,则返回输入数组而不是副本。

因为您有一个字符数组并且它需要转换为 int32,所以我认为这违反了 dtype 要求。

【讨论】:

【参考方案3】:

我找到了一种复杂的方式来进行就地类型转换

https://***.com/a/4396247/901925

在该示例中,转换是从“int32”到“float32”。适应我们的情况:

初始x 具有足够大的字符串大小:

In [128]: x=np.array(['0','1'],dtype='S4')
In [129]: x.__array_interface__['data']
Out[129]: (173756800, False)    # data buffer location

现在创建一个视图,并将值从 x 复制到视图:

In [130]: y=x.view(int)
In [131]: y[:]=x

相同的数据缓冲区位置(y 相同)

In [132]: x.__array_interface__['data']
Out[132]: (173756800, False)

现在y 是两个整数:

In [133]: y
Out[133]: array([0, 1])

x,仍然是S4,以不同的方式查看这些字节:

In [134]: x
Out[134]: 
array([b'', b'\x01'], 
      dtype='|S4')

因此,如果字节大小匹配,则可以就地执行数据类型转换,但这是一种高级操作。提出这个问题的人和回答这个问题的人都是numpy 专家。

另一个答案中提到了astype,copy=False,但由于与此处相同的原因而失败 - 它无法在不更改原始数组的情况下执行转换。

【讨论】:

【参考方案4】:

您应该阅读文档:

如果 copy 设置为 false,并且 dtype、order 和 subok 要求 满足,则返回输入数组而不是副本。

所以您的 dtype 要求没有得到满足。必须复制数组

【讨论】:

以上是关于为啥numpy数组的astype方法在转换类型时不修改输入?的主要内容,如果未能解决你的问题,请参考以下文章

numpy随笔-astype

再次对 Numpy 数组进行就地类型转换?

为啥numpy在执行list方法时不创建数组

Python的Numpy库的函数astype()在将大范围数据类型转换为小范围数据类型时并不是做饱和(saturate)操作(附实现饱和操作的方法)

numpy.astype(np.uint8) 如何转换浮点数组? -1.2997805 变为 255

使用NumPy库的函数astype()对ndarray的数据类型进行转换