为啥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.nbytes
和 b.nbytes
。一个是 2,另一个是 8。你和 numpy 不能将 2 个 4byte 整数压缩到 2 个 1byte 字符槽中。
【参考方案1】:
这里有两个明显的问题。一、
numpy.array(a)
在
b=numpy.array(a).astype(numpy.int32,copy=False)
已经制作了副本。二、来自docs:
如果[复制参数]设置为false,满足dtype、order、subok要求,输入数组返回而不是副本。
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方法在转换类型时不修改输入?的主要内容,如果未能解决你的问题,请参考以下文章
Python的Numpy库的函数astype()在将大范围数据类型转换为小范围数据类型时并不是做饱和(saturate)操作(附实现饱和操作的方法)