2017-07-07 34 views
1

我是編程和numpy的新手......在閱讀教程和在jupyter筆記本上進行實驗時......我想將numpy數組的dtype轉換爲如下:在NumPy數組中使用array.dtype = <data type>分配dtype值給出了不明確的結果

import numpy as np 
c = np.random.rand(4)*10 
print c 
#Output1: [ 0.12757225 5.48992242 7.63139022 2.92746857] 
c.dtype = int 
print c 
#Output2: [4593764294844833304 4617867121563982285 4620278199966380988 4613774491979221856] 

我知道改變的正確方法是:

c = c.astype(int) 

但我想在輸出2那些模棱兩可的數字背後的原因。他們是什麼?他們是什麼意思?

+1

我幾乎驚訝於直接分配是允許的。它只是感覺危險。直接分配'形狀'也是允許的,但我很少使用它。 – hpaulj

+0

@hpaulj與'strides'一樣的東西,我寧願留下所有這些屬性。 –

回答

3

浮點和整數(numpy.float64 s和numpy.int64 s)在內存中的表示方式不同。存儲在這些不同類型中的值42對應於存儲器中的不同位模式。

當你重新分配數組的dtype屬性,你把基礎數據不變,你告訴numpy的,以解釋位的一種新的方式該模式。由於現在的解釋與數據的原始定義不匹配,因此最終會出現亂碼(無意義的數字)。

在另一方面,通過.astype()轉換您的陣列會實際上是在內存中的數據轉換:

>>> import numpy as np 
>>> arr = np.random.rand(3) 
>>> arr.dtype 
dtype('float64') 
>>> arr 
array([ 0.7258989 , 0.56473195, 0.20885672]) 
>>> arr.data 
<memory at 0x7f10d7061288> 
>>> arr.dtype = np.int64 
>>> arr.data 
<memory at 0x7f10d7061348> 
>>> arr 
array([4604713535589390862, 4603261872765946451, 4596692876638008676]) 

正確的轉換:

>>> arr = np.random.rand(3)*10 
>>> arr 
array([ 3.59591191, 1.21786042, 6.42272461]) 
>>> arr.astype(np.int64) 
array([3, 1, 6]) 

正如你所看到的,使用astype將有意義的轉換數組的原始值,在這種情況下,它將截斷爲整數部分,並返回一個具有相應值的新數組和dtype

請注意,分配一個新的dtype不會觸發任何檢查,所以你可以做你的陣列非常奇怪的東西。在上面的例子中,64位浮點數被重新解釋爲64位整數。但你也可以改變位大小:

>>> arr = np.random.rand(3) 
>>> arr.shape 
(3,) 
>>> arr.dtype 
dtype('float64') 
>>> arr.dtype = np.float32 
>>> arr.shape 
(6,) 
>>> arr 
array([ 4.00690371e+35, 1.87285304e+00, 8.62005305e+13, 
     1.33751166e+00, 7.17894062e+30, 1.81315207e+00], dtype=float32) 

通過告訴numpy的,你的數據佔用一半的空間比原先,numpy的會推斷出你的陣列有兩倍多的元素!顯然不是你應該做的。


又如:考慮8位無符號整數255 == 2 ** 8-1:它對應於11111111以二進制。現在,試着重新詮釋其中兩個數字作爲一個單一的16位無符號整數:

>>> arr = np.array([255,255],dtype=np.uint8) 
>>> arr.dtype = np.uint16 
>>> arr 
array([65535], dtype=uint16) 

正如你所看到的,結果是單號65535。如果不按門鈴,這也正是2 ** 16-1,其中二進制模式有16個。兩個全1模式被重新解釋爲一個16位數字,結果相應改變。你經常看到更多的數字的原因是重新解釋浮點數,因爲整數反過來也會導致更強大的數據混亂,這是由於浮點數在內存中的表示方式。


hpaulj noted如,可以直接通過構建陣列的新view與改性dtype執行數據的此重新解釋。這可能比必須重新分配給定數組的dtype更有用,但是再次更改dtype僅在相當少見的非常具體的用例中才有用。

+1

實際上,它是'.view(int)'命令的就地版本。 – hpaulj

相關問題