我是Python新手,不明白是什么.dtype.
例如:
>>> aa
array([1, 2, 3, 4, 5, 6, 7, 8])
>>> aa.dtype = "float64"
>>> aa
array([ 4.24399158e-314, 8.48798317e-314, 1.27319747e-313,
1.69759663e-313])
Run Code Online (Sandbox Code Playgroud)
我认为dtype是aa的属性,应该是int,如果我赋值aa.dtype = "float64"
那么aa应该成为array([1.0 ,2.0 ,3.0, 4.0, 5.0, 6.0, 7.0, 8.0]).
为什么它会改变它的价值和规模?
这是什么意思?
我实际上是从一段代码中学习的,我应该在这里粘贴它:
def to_1d(array):
"""prepares an array into a 1d real vector"""
a = array.copy() # copy the array, to avoid changing global
orig_dtype = a.dtype
a.dtype = "float64" # this doubles the size of array
orig_shape = a.shape
return a.ravel(), (orig_dtype, orig_shape) #flatten and return
Run Code Online (Sandbox Code Playgroud)
我认为它不应该改变输入数组的值,而只是改变它的大小.对功能如何运作感到困惑
Joe*_*ton 42
首先,您正在学习的代码存在缺陷.几乎可以肯定的是,根据代码中的注释,原作者认为它没有做到.
作者可能的意思是:
def to_1d(array):
"""prepares an array into a 1d real vector"""
return array.astype(np.float64).ravel()
Run Code Online (Sandbox Code Playgroud)
但是,如果array总是一个复数的数组,那么原始代码就有了一些意义.
查看数组(a.dtype = 'float64'相当于做a = a.view('float64'))的唯一情况是它的大小加倍,如果它是一个复杂的数组(numpy.complex128)或128位浮点数组.对于任何其他dtype,它没有多大意义.
对于复杂数组的特定情况,原始代码会将类似的内容np.array([0.5+1j, 9.0+1.33j])转换为np.array([0.5, 1.0, 9.0, 1.33]).
一种更清晰的写作方式是:
def complex_to_iterleaved_real(array):
"""prepares a complex array into an "interleaved" 1d real vector"""
return array.copy().view('float64').ravel()
Run Code Online (Sandbox Code Playgroud)
(我现在忽略了关于返回原始dtype和形状的部分.)
要解释这里发生了什么,你需要了解numpy数组是什么.
numpy数组由"原始"内存缓冲区组成,通过"视图"将其解释为数组.您可以将所有numpy数组视为视图.
在numpy意义上,视图只是切片和切割相同内存缓冲区而不进行复制的不同方式.
视图具有形状,数据类型(dtype),偏移和步幅.在可能的情况下,numpy数组上的索引/整形操作将只返回原始内存缓冲区的视图.
这意味着喜欢y = x.T或y = x[::2]不使用任何额外内存的东西,不要复制x.
所以,如果我们有一个类似于此的数组:
import numpy as np
x = np.array([1,2,3,4,5,6,7,8,9,10])
Run Code Online (Sandbox Code Playgroud)
我们可以通过以下两种方式重塑它:
x = x.reshape((2, 5))
Run Code Online (Sandbox Code Playgroud)
要么
x.shape = (2, 5)
Run Code Online (Sandbox Code Playgroud)
为了便于阅读,第一个选项更好.但它们(几乎)完全相同.两个人都不会制作一个会占用更多内存的副本(第一个会产生一个新的python对象,但现在不在这一点上.).
同样适用于dtype.我们可以通过设置x.dtype或调用将数组视为不同的dtype x.view(...).
所以我们可以这样做:
import numpy as np
x = np.array([1,2,3], dtype=np.int)
print 'The original array'
print x
print '\n...Viewed as unsigned 8-bit integers (notice the length change!)'
y = x.view(np.uint8)
print y
print '\n...Doing the same thing by setting the dtype'
x.dtype = np.uint8
print x
print '\n...And we can set the dtype again and go back to the original.'
x.dtype = np.int
print x
Run Code Online (Sandbox Code Playgroud)
产量:
The original array
[1 2 3]
...Viewed as unsigned 8-bit integers (notice the length change!)
[1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0]
...Doing the same thing by setting the dtype
[1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0]
...And we can set the dtype again and go back to the original.
[1 2 3]
Run Code Online (Sandbox Code Playgroud)
但请记住,这可以让您对内存缓冲区的解释方式进行低级控制.
例如:
import numpy as np
x = np.arange(10, dtype=np.int)
print 'An integer array:', x
print 'But if we view it as a float:', x.view(np.float)
print "...It's probably not what we expected..."
Run Code Online (Sandbox Code Playgroud)
这会产生:
An integer array: [0 1 2 3 4 5 6 7 8 9]
But if we view it as a float: [ 0.00000000e+000 4.94065646e-324
9.88131292e-324 1.48219694e-323 1.97626258e-323
2.47032823e-323 2.96439388e-323 3.45845952e-323
3.95252517e-323 4.44659081e-323]
...It's probably not what we expected...
Run Code Online (Sandbox Code Playgroud)
因此,在这种情况下,我们将原始内存缓冲区的底层位解释为浮点数.
如果我们想要将int重新制作为浮点数来创建一个新副本,我们将使用x.astype(np.float).
复数存储(在C,python和numpy中)作为两个浮点数.第一个是实部,第二个是虚部.
所以,如果我们这样做:
import numpy as np
x = np.array([0.5+1j, 1.0+2j, 3.0+0j])
Run Code Online (Sandbox Code Playgroud)
我们可以看到real(x.real)和imaginary(x.imag)部分.如果我们将它转换为浮点数,我们会收到关于丢弃虚部的警告,我们将得到一个只包含实部的数组.
print x.real
print x.astype(float)
Run Code Online (Sandbox Code Playgroud)
astype 制作副本并将值转换为新类型.
但是,如果我们将这个数组视为一个浮点数,我们将得到一个序列item1.real, item1.imag, item2.real, item2.imag, ....
print x
print x.view(float)
Run Code Online (Sandbox Code Playgroud)
收益率:
[ 0.5+1.j 1.0+2.j 3.0+0.j]
[ 0.5 1. 1. 2. 3. 0. ]
Run Code Online (Sandbox Code Playgroud)
每个复数基本上都是两个浮点数,所以如果我们改变numpy如何解释底层内存缓冲区,我们得到一个两倍长度的数组.
希望这有助于清理一些事情......
通过以这种方式更改dtype,您将改变解释固定内存块的方式.
例:
>>> import numpy as np
>>> a=np.array([1,0,0,0,0,0,0,0],dtype='int8')
>>> a
array([1, 0, 0, 0, 0, 0, 0, 0], dtype=int8)
>>> a.dtype='int64'
>>> a
array([1])
Run Code Online (Sandbox Code Playgroud)
注意从变化如何int8到int64改变的8元件,8位整数数组,为1个元件,64位阵列.然而,它是相同的8字节块.在具有本机endianess的i7机器上,字节模式与1int64格式相同.
改变1的位置:
>>> a=np.array([0,0,0,1,0,0,0,0],dtype='int8')
>>> a.dtype='int64'
>>> a
array([16777216])
Run Code Online (Sandbox Code Playgroud)
另一个例子:
>>> a=np.array([0,0,0,0,0,0,1,0],dtype='int32')
>>> a.dtype='int64'
>>> a
array([0, 0, 0, 1])
Run Code Online (Sandbox Code Playgroud)
改变132字节,32位数组的位置:
>>> a=np.array([0,0,0,1,0,0,0,0],dtype='int32')
>>> a.dtype='int64'
>>> a
array([ 0, 4294967296, 0, 0])
Run Code Online (Sandbox Code Playgroud)
它是重新解释的相同位块.
| 归档时间: |
|
| 查看次数: |
33017 次 |
| 最近记录: |