5

データが数値であるが、小数点記号としてカンマが付いている、かなり大きな(> 0.5MB)ファイルがたくさん(数十万)あります。のような外部ツールを使用するのは現実的ではありませんsed "s/,/./g"。区切り記号がドットの場合は を使用するだけですtextscan(fid, '%f%f%f')が、小数点記号を変更するオプションがありません。このようなファイルを効率的に読み取るにはどうすればよいですか?

ファイルからのサンプル行:

5,040000    18,040000   -0,030000

注: R についても同様の質問がありますが、私は Matlab を使用しています。

4

4 に答える 4

4

テスト スクリプトを使用して、係数が 1.5 未満であることがわかりました。私のコードは次のようになります。

tmco = {'NumHeaderLines', 1      , ...
        'NumColumns'    , 5      , ...
        'ConvString'    , '%f'   , ...
        'InfoLevel'     , 0      , ...
        'ReadMode'      , 'block', ...
        'ReplaceChar'   , {',.'} } ;

A = txt2mat(filename, tmco{:});

異なる 'ReplaceChar' 値と 'ReadMode' 'block' に注意してください。

私の(あまり新しくない)マシンで、〜5MBのファイルに対して次の結果が得られます。

  • txt2mat テスト コンマ平均。時間: 0.63231
  • txt2mat テスト ドット平均 時間: 0.45715
  • textscan テスト ドット平均 時間: 0.4787

私のテストスクリプトの完全なコード:

%% generate sample files

fdot = 'C:\temp\cDot.txt';
fcom = 'C:\temp\cCom.txt';

c = 5;       % # columns
r = 100000;  % # rows
test = round(1e8*rand(r,c))/1e6;
tdot = sprintf([repmat('%f ', 1,c), '\r\n'], test.'); % '
tdot = ['a header line', char([13,10]), tdot];

tcom = strrep(tdot,'.',',');

% write dot file
fid = fopen(fdot,'w');
fprintf(fid, '%s', tdot);
fclose(fid);
% write comma file
fid = fopen(fcom,'w');
fprintf(fid, '%s', tcom);
fclose(fid);

disp('-----')

%% read back sample files with txt2mat and textscan

% txt2mat-options with comma decimal sep.
tmco = {'NumHeaderLines', 1      , ...
        'NumColumns'    , 5      , ...
        'ConvString'    , '%f'   , ...
        'InfoLevel'     , 0      , ...
        'ReadMode'      , 'block', ...
        'ReplaceChar'   , {',.'} } ;

% txt2mat-options with dot decimal sep.
tmdo = {'NumHeaderLines', 1      , ...
        'NumColumns'    , 5      , ...
        'ConvString'    , '%f'   , ...
        'InfoLevel'     , 0      , ...
        'ReadMode'      , 'block'} ;

% textscan-options
tsco = {'HeaderLines'   , 1      , ...
        'CollectOutput' , true   } ;


A = txt2mat(fcom, tmco{:});
B = txt2mat(fdot, tmdo{:});

fid = fopen(fdot);
C = textscan(fid, repmat('%f',1,c) , tsco{:} );
fclose(fid);
C = C{1};

disp(['txt2mat  test comma (1=Ok): ' num2str(isequal(A,test)) ])
disp(['txt2mat  test dot   (1=Ok): ' num2str(isequal(B,test)) ])
disp(['textscan test dot   (1=Ok): ' num2str(isequal(C,test)) ])
disp('-----')

%% speed test

numTest = 20;

% A) txt2mat with comma
tic
for k = 1:numTest
    A = txt2mat(fcom, tmco{:});
    clear A
end
ttmc = toc;
disp(['txt2mat  test comma avg. time: ' num2str(ttmc/numTest) ])

% B) txt2mat with dot
tic
for k = 1:numTest
    B = txt2mat(fdot, tmdo{:});
    clear B
end
ttmd = toc;
disp(['txt2mat  test dot   avg. time: ' num2str(ttmd/numTest) ])

% C) textscan with dot
tic
for k = 1:numTest
    fid = fopen(fdot);
    C = textscan(fid, repmat('%f',1,c) , tsco{:} );
    fclose(fid);
    C = C{1};
    clear C
end
ttsc = toc;
disp(['textscan test dot   avg. time: ' num2str(ttsc/numTest) ])
disp('-----')
于 2011-12-13T10:41:23.393 に答える
0

を使用できますtxt2mat

A = txt2mat('data.txt');

データを自動的に処理します。ただし、次のように明示的に言うことができます。

A = txt2mat('data.txt','ReplaceChar',',.');

PS 効率的ではないかもしれませんが、特定のデータ形式にのみ必要な場合は、ソース ファイルからパーツをコピーできます。

于 2011-11-20T19:51:17.180 に答える
0

私の解決策(コンマは小数点以下のプレースホルダーとしてのみ使用され、空白は列を区切ると仮定します):

fid = fopen("FILENAME");
indat = fread(fid, '*char');
fclose(fid);
indat = strrep(indat, ',', '.');
[colA, colB] = strread(indat, '%f %f');

私が行ったように、単一のヘッダー行を削除する必要がある場合は、これでうまくいくはずです:

fid = fopen("FILENAME");                  %Open file
indat = fread(fid, '*char');              %Read in the entire file as characters
fclose(fid);                              %Close file
indat = strrep(indat, ',', '.');          %Replace commas with periods
endheader=strfind(indat,13);              %Find first newline
indat=indat(endheader+1:size(indat,2));   %Extract all characters after first new line
[colA, colB] = strread(indat, '%f %f');   %Convert string to numerical data
于 2012-10-08T12:00:35.177 に答える
0

ファイル分析をバイパスするために、ヘッダー行の数と、可能であれば列の数を入力として追加することで、txt2mat を高速化することもできます。その場合、ドット区切りの小数を使用したテキストスキャンのインポートと比較して、25 倍になることはありません。(mathworks サイトの著者ページを使用して私に連絡することもできます。) matlab でカンマ区切りの小数を処理するより効率的な方法を見つけた場合はお知らせください。

于 2011-12-09T23:45:34.907 に答える