2017-02-23 61 views
1

我想使用np.fromfile從二進制文件創建numpy數組。該文件包含一個3D數組,並且我只關心每個幀中的某個單元格。使用numpy.fromfile加載每第n個元素

x = np.fromfile(file, dtype='int32', count=width*height*frames) 
vals = x[5::width*height] 

上面的代碼在理論上的工作,但我的文件非常大,閱讀這一切到x導致內存錯誤。有沒有辦法使用fromfile僅以vals開頭?

+0

如果您傳遞文件,而不是第一個參數的字符串,那麼您可以簡單地使用'count'關鍵字以易於管理的塊讀取文件。 –

+0

Count可以讓您讀取前N個元素,但它不會幫助您加載每個第n個元素。文件是串行存儲。將每第n個項目讀到最後仍然需要讀取文件到最後。 – hpaulj

+0

@hpaulj是的,但在較小的塊OP可以使用他們的發佈代碼。如果抽取結果適合內存,我不明白爲什麼這不應該工作。或者我在這裏錯過了什麼? –

回答

-1

這可能是效率極其低下的,但它的工作原理:

import numpy as np 

def read_in_chunks(fn, offset, step, steps_per_chunk, dtype=np.int32): 
    out = [] 
    fd = open(fn, 'br') 
    while True: 
     chunk = (np.fromfile(fd, dtype=dtype, count=steps_per_chunk*step) 
       [offset::step]) 
     if chunk.size==0: 
      break 
     out.append(chunk) 
    return np.r_[tuple(out)] 

x = np.arange(100000) 
x.tofile('test.bin') 
b = read_in_chunks('test.bin', 2, 100, 6, int) 
print(b) 

更新:

下面是一個使用seek跳過不需要的東西。它適用於我,但完全承諾。

def skip_load(fn, offset, step, dtype=np.float, n = 10**100): 
    elsize = np.dtype(dtype).itemsize 
    step *= elsize 
    offset *= elsize 
    fd = open(fn, 'rb') if isinstance(fn, str) else fn 
    out = [] 
    pos = fd.tell() 
    target = ((pos - offset - 1) // step + 1) * step + offset 
    fd.seek(target) 
    while n > 0: 
     if (fd.tell() != target): 
      return np.frombuffer(b"".join(out), dtype=dtype) 
     out.append(fd.read(elsize)) 
     n -= 1 
     if len(out[-1]) < elsize: 
      return np.frombuffer(b"".join(out[:-1]), dtype=dtype) 
     target += step 
     fd.seek(target) 
    return np.frombuffer(b"".join(out), dtype=dtype)