外部ファイルからデータを読み込む

できるだけ楽に.
手間のかからない順に上から並べています.
【訂正】しばらくFormatSpecの例文に'%e'と書いておりましたが,'%f'でした.すみません.

load

  • 数値データのみで文字列を含まず,かつデータ列数が全行等しい場合
    dataorg = load(filename);
    で問題ない.

dlmread

  • 読み込み不要なヘッダー行がある場合
    dataorg = dlmread(filename,Delimiter,R1,C1);
    R1は読み取り開始行のオフセット.
    csvファイル,ヘッダー3行とすると,
    dataorg = dlmread(filename,',',3,0);
    で4行1列目から読み取りをする.
  • 空白区切りのファイル,ヘッダー行がある場合
    dataorg = dlmread(filename,'',3,0);
    にしてDelimiterの部分に何も入れない.
    Delimiter部分にスペースを入れると,連続した空白をそれぞれDelimiterとして扱ってしまう.

importdata

  • 文字列を含んだデータがある場合
    dataorg = importdata(filename,DelimiterIn,HeaderlinesIn)
    この場合,dataorgは構造体となり,文字列を含んだデータ列と,数値のデータ列はそれぞれ,
    dataorg.textdata
    dataorg.data
    として格納される.
    importdataは文字列と数値が混在し,データ列数がバラバラでも一応読み込める.
    ただしその場合は読み込んだ順番で文字列も数値も縦一列にデータが並んだりする.データ抽出が困難なためあまり意味がない.

textscan

  • データ列数が統一されていないファイルなど,その他全て
    テキストと数値が混在するファイルは大抵textscanになると思う.
    fopenで開いて,textscanで読み取って,fcloseで閉じる.
%例1
dataorg = textscan(fileID,FormatSpec,N,'HeaderLines',3);
%例2
dataorg = textscan(fileID,FormatSpec,'HeaderLines',3);

例1では,FormatSpecで指定した形式をN回分読み込む.
例2では,FormatSpecで指定した形式で読み込める限り,つまり同じformatが続いているだけ,またはファイルの最後まで読み込む.
たとえば,Fortranによって

!(注)Fortranのコードです
FORMAT(<nx>f10.3)            !例① 固定長の数値がnx個分横に並ぶ
FORMAT(<nx>(1pe12.3,","))    !例② 数値のみのcsv
FORMAT(a,",",<nx>(f0.2,",")) !例③ 最初の列に文字列があるcsv

という形式で出力されたファイルの場合,FormatSpecの部分を

repmat('%10.3f',[1 nx])      % 例①
repmat('%f,',[1 nx])         % 例②
['%s,',repmat('%f,',[1 nx])] % 例③

とする.
csvファイル等は,行末のカンマ(,)の有無によってFormatSpecの書き方が変わるので注意.下記参照.

!(注)Fortranのコードです
FORMAT(<nx-1>(1pe12.3,","),1pe12.3)  !例②' 行末カンマなし
% MATLAB textscanのFormatSpec
[repmat('%f,',[1 nx-1]),'%f\n'] % 例②' \nは無くても可

他の関数と同様,区切り文字が統一されていれば,FormatSpecにカンマ等を含めずとも

dataorg = textscan(fileID,FormatSpec,'Delimiter',',');

でOK.
textscanで読み込むと,読み込んだ変数はセル配列になる.規則正しい配列で,数値データのみであれば

hoge = cell2mat(dataorg)

でセル配列でないmatrixデータとなる.
文字列形式'%s'はDelimiterを指定しないと,空白を勝手に区切りとして扱ってしまうためなかなか厄介.空白の数がわかる場合や文字列の幅が決まっているときはちゃんと指定する.
行の残りの部分を読み込まずに改行'\n'までスキップする場合は,

'%*[^\n]'

を付け加える.例えば,

Time =   2.000000, X = 0.005, ......

というテキストの数値部分だけがほしい場合には,FormatSpecを

'Time =%f,X =%f%*[^\n]'

とする.
fopen,textscan,fcloseは最も融通が利くが,割と面倒.

fscanf

  • textscanと同様,自由形式ファイル
    こちらもfopenとfcloseでファイルの開閉を行う.
    fscanfは,その時の読み取り位置が行末("\n"=改行コードの手前)なのか,行頭("\n"の次)なのか留意が必要.
    textscanのように,FormatSpecに'%*[^\n]'を含めて次の改行位置までスキップすることはできない.
    hoge = fgetl(fid);
    を使うと,読み取り位置から次の改行位置までhogeにtextが格納されるので,ヘッダー行の回数分だけ実行すれば,読み飛ばすことができる.
    この時,読み取り開始位置が行末にあると,hogeには何も入らずに次の行頭に移動するだけになる.
    上記textscanで示した例②のフォーマットが縦にny行分あるとすると,以下のようにすることでデータ元の配列通りに読み込みが可能.
    fmt = repmat('%f,',[1 nx*ny]);
    fid = fopen(filename,'r');
    dataorg = fscanf(fid,fmt,[nx ny])';
    fclose(fid);
    ny行nx列でも,"[nx ny]"となる点に注意.転置記号が重要.

textscanとfscanfの使い分け

textscanはセル配列になるので,たぶんfscanfの方が速い.
↑と思ったら,while文で試したところ,fscanfの方が遅かった.
文字列と数値が混在するファイルから読み取る際のtextscanとfscanfの個人的な使い分けは以下の通り.

fscanf  : n行目の特定の文字列の後ろにある数値を1つだけ or
          n行目~m行目の2次元matrixの数値だけをインポート
textscan: 上記以外

textを読むには名の通りtextscanの方が向いていると思う.
数値の扱いについても,便利なので何かとtextscanを使ってしまいがち.


Front page   Edit Diff Attach Copy Rename Reload   New List of pages Search Recent changes   Help   RSS of recent changes
Last-modified: 2017-10-20 (Fri) 07:21:06 (3h)