2017-02-23 4 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) 
関連する問題