私はハードディスク上のバイナリファイルに格納されている非常に大きなデータセットを持っています。ここでは、ファイル構造の例である:バイナリファイルからナンシーアレイを効率的に作成する方法
ファイルヘッダは
4 Byte Int - Record Timestamp
サンプル開始
149 Byte ASCII Header
録音スタート
2 Byte Int - Data Stream 1 Sample
2 Byte Int - Data Stream 2 Sample
2 Byte Int - Data Stream 3 Sample
2 Byte Int - Data Stream 4 Sample
サンプルエンド
レコードごとに122,880サンプル、ファイルごとに713レコードがあります。これにより、合計サイズは700,910,521バイトになります。サンプルレートとレコード数は時々異なりますので、ファイルごとにそれぞれの数を検出するようにコーディングする必要があります。
現在、私は配列にこのデータをインポートするために使用したコードは次のように動作します。
from time import clock
from numpy import zeros , int16 , int32 , hstack , array , savez
from struct import unpack
from os.path import getsize
start_time = clock()
file_size = getsize(input_file)
with open(input_file,'rb') as openfile:
input_data = openfile.read()
header = input_data[:149]
record_size = int(header[23:31])
number_of_records = (file_size - 149)/record_size
sample_rate = ((record_size - 4)/4)/2
time_series = zeros(0,dtype=int32)
t_series = zeros(0,dtype=int16)
x_series = zeros(0,dtype=int16)
y_series = zeros(0,dtype=int16)
z_series = zeros(0,dtype=int16)
for record in xrange(number_of_records):
time_stamp = array(unpack('<l' , input_data[ 149 + (record * record_size) : 149 + (record * record_size) + 4 ]) , dtype = int32)
unpacked_record = unpack('<' + str(sample_rate * 4) + 'h' , input_data[ 149 + (record * record_size) + 4 : 149 + ((record + 1) * record_size) ])
record_t = zeros(sample_rate , dtype=int16)
record_x = zeros(sample_rate , dtype=int16)
record_y = zeros(sample_rate , dtype=int16)
record_z = zeros(sample_rate , dtype=int16)
for sample in xrange(sample_rate):
record_t[sample] = unpacked_record[ (sample * 4) + 0 ]
record_x[sample] = unpacked_record[ (sample * 4) + 1 ]
record_y[sample] = unpacked_record[ (sample * 4) + 2 ]
record_z[sample] = unpacked_record[ (sample * 4) + 3 ]
time_series = hstack ((time_series , time_stamp))
t_series = hstack ((t_series , record_t))
x_series = hstack ((x_series , record_x))
y_series = hstack ((y_series , record_y))
z_series = hstack ((z_series , record_z))
savez(output_file, t=t_series , x=x_series ,y=y_series, z=z_series, time=time_series)
end_time = clock()
print 'Total Time',end_time - start_time,'seconds'
これは、現在、私には非常に高いと思われる700メガバイトのファイル、あたり約250秒かかります。私はこれを行うより効率的な方法がありますか?上記元のコードより27X速い9秒にランタイムを切断DTYPEカスタムとnumpyのFROMFILE方法を用いて最終ソリューション
。最終的なコードは以下の通りです。
from numpy import savez, dtype , fromfile
from os.path import getsize
from time import clock
start_time = clock()
file_size = getsize(input_file)
openfile = open(input_file,'rb')
header = openfile.read(149)
record_size = int(header[23:31])
number_of_records = (file_size - 149)/record_size
sample_rate = ((record_size - 4)/4)/2
record_dtype = dtype([ ('timestamp' , '<i4') , ('samples' , '<i2' , (sample_rate , 4)) ])
data = fromfile(openfile , dtype = record_dtype , count = number_of_records)
time_series = data['timestamp']
t_series = data['samples'][:,:,0].ravel()
x_series = data['samples'][:,:,1].ravel()
y_series = data['samples'][:,:,2].ravel()
z_series = data['samples'][:,:,3].ravel()
savez(output_file, t=t_series , x=x_series ,y=y_series, z=z_series, fid=time_series)
end_time = clock()
print 'It took',end_time - start_time,'seconds'
は、それが医療データですか? EDF?私が何を話しているのかわからない場合は、気にしないでください...;)とにかく、私はこの質問に従って医療データバイナリファイルを開くために私の答えを見てください:http://stackoverflow.com/q/5804052/401828。そこには興味深い議論があります。 – heltonbiker
データは地球物理学ではありません。私は投稿する前に調査中にあなたの質問を見ました。あなたのデータは短いものだけで構成されています。残念ながら、ストリーム全体に4バイトのintタイムスタンプが散在しています。 – Stu
何の価値があるのか、numpyの構造化配列の多くの操作は、通常のnumpy配列よりもずっと遅いです。インポート時間は速くなるかもしれませんが、計算に10-100倍かかることがあります:( –