2015-09-24 33 views
2

我有一個自定義dtype my_type的數組,我從二進制文件中成功讀取。自定義dtype在數據之後有一個標題部分。數據部分是np.int16數字,因此自定義D型看起來是這樣的:numpy自定義dtype質詢

header, imaginary, real, imaginary, real, ..., imaginary, real 

現在我正在尋找使用numpy的的觀點得到的np.complex64數組一個聰明的辦法的只有數據無複製/循環等考慮以下事實:

  • 頭部分應該得到某種忽略
  • 糾正順序(即第一個真實的,想象的)
  • 結果數組應該是complex64不復雜32!

也就是說,從定製的D型數組:

[my_type, my_type, ..., my_type] 

我想獲得包含一個更大的陣列:

[complex64, complex64, ..., complex64] 

是否有可能用做一氣呵成Numpy的查看

UPDATE:

因此,解決辦法是在內存中拷貝。非常感謝下面的答案。但是由於令人討厭的標題出現在每個數據幀之前,似乎儘管在內存中進行了複製,但仍然需要在所有數據幀上進行循環。在示意性的方式,我有:

a = np.arange(10, dtype=np.float16) 
skip_annoying_header = 2 
r = np.zeros(a.size - skip_annoying_header, np.float16) 
r[0::2], r[1::2] = a[skip_annoying_header + 1::2], a[skip_annoying_header::2] 
r = r.astype(np.float32) 
r = r.view(np.complex64) 

,我這樣做是一個for循環的每個數據幀,然後在for循環結束時,我再次r內容複製到陣列。

這個循環可以以某種方式消除?

+0

很難,當你在文件上談論的數據告訴,以及你已經加載的數組。在讀取數據時轉換數據一次只能從文件讀取一個「數據幀」是一回事,轉換結構化數組是另一回事。如果你已經有陣列顯示它是'dtype'和'shape'。 – hpaulj

回答

3

所有3個需求與view衝突。

忽略header字段需要選擇其他字段。選擇單個字段顯然是一個視圖,但多個字段的狀態正在變化。當我嘗試任何事情,除了簡單地查看值我得到一個警告:

In [497]: dt=np.dtype('U10,f,f,f,f') 
In [498]: x=np.zeros((5,),dt) 

In [505]: x[['f1','f3']].__array_interface__ 
/usr/bin/ipython3:1: FutureWarning: Numpy has detected that you (may be) writing to an array returned 
by numpy.diagonal or by selecting multiple fields in a record 
array. This code will likely break in a future numpy release -- 
see numpy.diagonal or arrays.indexing reference docs for details. 
The quick fix is to make an explicit copy (e.g., do 
arr.diagonal().copy() or arr[['f0','f1']].copy()). 

記住,數據是通過元素奠定了元素,緊湊塊D型元組值 - 顯示器基本上壓縮版本。忽略header需要跳過該組字節。 view可以處理由strides生成的跳過,但不能處理這些dtype字段跳過。

In [533]: x 
Out[533]: 
array([('header', 0.0, 5.0, 1.0, 10.0), ('header', 1.0, 4.0, 1.0, 10.0), 
     ('header', 2.0, 3.0, 1.0, 10.0), ('header', 3.0, 2.0, 1.0, 10.0), 
     ('header', 4.0, 1.0, 1.0, 10.0)], 
     dtype=[('f0', '<U10'), ('f1', '<f4'), ('f2', '<f4'), ('f3', '<f4'), ('f4', '<f4')]) 

探討重新排序複雜的領域,讓我們嘗試一個二維數組:

In [509]: y=np.arange(10.).reshape(5,2) # 2 column float 
In [510]: y.view(complex) # can be viewed as complex 
Out[510]: 
array([[ 0.+1.j], 
     [ 2.+3.j], 
     [ 4.+5.j], 
     [ 6.+7.j], 
     [ 8.+9.j]]) 
In [511]: y[:,::-1].view(complex) 
... 
ValueError: new type not compatible with array. 

切換真正/ imaginay列我必須做出一個副本。 complex要求2浮游物是連續的和有序的。

In [512]: y[:,::-1].copy().view(complex) 
Out[512]: 
array([[ 1.+0.j], 
     [ 3.+2.j], 
     [ 5.+4.j], 
     [ 7.+6.j], 
     [ 9.+8.j]]) 

float32float64顯然不是一個view變化。一個使用每個數字4個字節,另一個8個。如果不復制,您不能'查看'4個8。

+0

這很好。我不知道有關連續數據的要求。我想知道在速度方面複製「成本」有多少... – xaratustra

2

@hpaulj絕對正確,這與觀點相沖突。

但是,您可能會問錯誤的問題。

numpy當然可以做你想做的事,但你需要在內存中做一個臨時副本。總體而言,通過重新思考「將整個文件讀入內存然後查看」方法,您可能會更好地服務於此。而是查找過去(或讀入)標題,然後用fromfile讀取數據部分。除此之外,只要您不需要將副本從float32改爲float64,就可以相對簡單地將事情操作到您想要的內容。


要下手了,讓我們產生類似你這樣的文件:

import numpy as np 

reals = np.arange(100).astype(np.float32) 
imag = -9999.0 * np.ones(100).astype(np.float32) 

data = np.empty(reals.size + imag.size, dtype=np.float32) 
data[::2], data[1::2] = imag, reals 

with open('temp.dat', 'wb') as outfile: 
    # Write a 1Kb header (of literal "x"'s, in this case) 
    outfile.write(1024 * 'x') 
    outfile.write(data) 

現在,我們將在閱讀

的關鍵在於忽視了頭部是seek過去吧然後用fromfile讀取數據。

然後,我們可以解交錯數據並同時轉換爲64位浮點數。

最後,您可以查看產生的2xN長度爲float64的數組作爲N長度complex128數組。 (注:complex128是一個複數的64位版本complex64是32位版本。)

例如:

import numpy as np 

with open('temp.dat', 'rb') as infile: 
    # Seek past header 
    infile.seek(1024) 

    # Read in rest of file as float32's 
    data = np.fromfile(infile, dtype=np.float32) 

result = np.empty(data.size, np.float64) 

# De-interleave imag & real back into expected real & imag, converting to 64-bit 
result[::2], result[1::2] = data[1::2], data[::2] 

# View the result as complex128's (i.e. 64-bit complex numbers) 
result = result.view(np.complex128) 
+0

感謝您的回答。事實上,我正在使用'seek',因爲這些文件通常很大,每個文件最多可以達到2GB。但問題是惱人的標題出現在每個數據幀之前,所以似乎循環是必要的.... – xaratustra