2013-10-03 9 views
5

大きなテキストファイル入力(〜500k行)とそれに続くのに関するパフォーマンスの問題があります。拡張されたパフォーマンスを持つテキストファイルから再配線を削除する

2つのヘッダ行がテキストファイルのどこかに再表示することができることpecularityと、以下の例示的な構造を有するテキストファイルdata.txtを検討:

Name Date Val1 val2 
--- ------- ---- ---- 
BA 2013-09-07 123.123 1232.22 
BA 2013-09-08 435.65756 2314.34 
BA 2013-09-09 234.2342 21342.342 

Iが書いたコードが動作されている以下の:

%# Read in file using textscan, read all values as string 

inFile = fopen('data.txt','r'); 
DATA = textscan(inFile, '%s %s %s %s'); 
fclose(inFile); 

%# Remove the header lines everywhere in DATA: 
%# Search indices of the first entry in first cell, i.e. 'Name', and remove 
%# all lines corresponding to those indices 

[iHeader,~] = find(strcmp(DATA{1},DATA{1}(1))); 
for i=1:length(DATA) 
    DATA{i}(iHeader)=[]; 
end 

%# Repeat again, the first entry corresponds now to '---' 

[iHeader,~] = find(strcmp(DATA{1},DATA{1}(1))); 
for i=1:length(DATA) 
    DATA{i}(iHeader)=[]; 
end 

%# Now convert the cells for column Val1 and Val2 in data.txt to doubles 
%# since they have been read in as strings: 

for i=3:4 
    [A] = cellfun(@str2double,DATA{i}); 
    DATA{i} = A; 
end 

私はオーデルの文字列がDATAの至る所にヘッダー行を削除することができるようにすべてを読み込むことにしました。

時間を停止すると、と比較して、str2doubleの方が早い選択肢ですが、コードの最も遅い部分が変換[A] = cellfun(@str2double,DATA{i})であることがわかります。 2番目に遅い部分はtextscanです。

この問題を解決するには、より早い方法がありますか?

さらに明確にする必要がある場合はお知らせください。私が見たことのない非常に明白な解決策があるなら、私は今3週間Matlabに取り組んでいます。

答えて

4

あなたはあなたのファイルの一部(あなたの場合は繰り返し2 headerlines)をスキップし、一回の関数コールでファイルを読み込みますCommentStyleと呼ばれるtextscanのオプションを使用することができます。

doc saysCommentStyleは2通りの方法で用いることができる:例えば'%'として単一の文字列を同じ行の文字列、あるいは{'/*', '*/'}のような2つの文字列のセルアレイ次の文字を無視する、との間の文字を無視します2つの文字列(行末を含む)。ここでは2番目のオプションを使用します:Name-の間の文字を削除します。末尾の文字列は、繰り返しの-文字で構成されているため、文字列全体を指定する必要があります。

inFile = fopen('data.txt','r'); 
DATA = textscan(inFile, '%s %s %f %f', ... 
     'Commentstyle', {'Name';'--- ------- ---- ----'}); 
fclose(inFile); 

あなたはdatenumを使用して意味のある数値に日付文字列を変換することができます。

DATA_date = datenum(C{2}) 
+0

これは私のデータでうまくいきました。文字列を二重に変換するのを避けると、時間が約60%短縮されます! – Lukas

2

これを避けるためにデータ取得を修正することが可能であれば、より長期的には、HeaderLinesをtextscanに利用することができます。

このコード例は、可能であればc3/c4を事前に割り当てます(つまり、サイズの上限とトリミングゼロを後で見積もることによって)。基本的には、最初にtextscanを呼び出すと、最初の2行をスキップし、フォーマットと互換性のない行(繰り返しヘッダーの途中など)に達するか、ファイルの最後に到達するまで続行します。それはそれが得た位置を覚えている。

textscanが次に呼び出されると、その行の残りの行と次の行全体がスキップされ、次にeofまたは別のヘッダー行のセットなどが続きます。ファイルの最後に達した場合、textscanはエラーなしで実行されますが、length(data{3})はゼロになります。

c3 = []; 
c4 = []; 
fid = fopen('data.txt'); 
data = textscan(fid,'%s %s %f %f','HeaderLines',2); 
l = length(data{3}); 
while l>0 %stop when we hit eof 
    c3 = [c3; data{3}]; 
    c4 = [c4; data{4}]; 
    data = textscan(fid,'%s %s %f %f','HeaderLines',2); 
    l = length(data{3}); 
end 
+0

私はこのアプローチが大好きです。私は@Maglaの答えと比較して、2つの(または他のN個の)ヘッダー行の特定のものを必要としません。私のコードでは、Maglaのソリューションは実装が短かったので、私はそれを最も適切な答えとして選択しました。また、 'commentstyle'を使った速度に関しては50%高速です。 – Lukas

関連する問題