#author("2020-05-31T13:23:23+09:00","default:Miyashita","Miyashita") #author("2020-07-14T14:51:23+09:00","default:Miyashita","Miyashita") //#htmlinsert(use_prettify_all.html) *外部ファイルからのデータ読み取り [#ya21bd81] できるだけ楽に.~ 手間のかからない順に上から並べています.~ #contents **load [#baaf6ced] -数値データのみで文字列を含まず,かつデータ列数が全行等しい場合 #codeprettify(lang-matlab){{ dataorg = load(filename); }} で問題ない.~ 固定長の出力で前後のデータに空白がない場合にはエラーを返すので注意.~ ~ ~ **dlmread (deprecated)[#u97f3f4e] 注意点1 Delimiter(区切り文字)が統一されている場合に限る.~ 注意点2 文字列には対応していない.読み飛ばす部分以外に文字列があってはいけない.~ Fortran の出力でいうと特に "*****" に注意.数値のみを書きだしたつもりでも,桁数の不足により文字列を出力することもある.~ NaN はあっても大丈夫だった気がする.~ -読み込み不要なヘッダー行がある場合 #codeprettify(lang-matlab){{ dataorg = dlmread(filename,Delimiter,R1,C1); }} R1は読み取り開始行のオフセット.~ csvファイル,ヘッダー3行とすると, #codeprettify(lang-matlab){{ dataorg = dlmread(filename,',',3,0); }} で4行1列目から読み取りをする.~ ~ -空白区切りのファイル,ヘッダー行がある場合 #codeprettify(lang-matlab){{ dataorg = dlmread(filename,'',3,0); }} にして Delimiter の部分に何も入れない.~ Delimiter 部分にスペースを入れると,連続した空白をそれぞれ Delimiter として扱ってしまう.~ ~ R2019a 以降の MATLAB では dlmread は非推奨になり,[[readmatrix>https://www.mathworks.com/help/matlab/ref/readmatrix.html]] を使うように,とのこと.~ ~ ~ **readmatrix [#o01ec050] R2019a 以降のバージョンで使用可能.~ dlmread と xlsread が統合されたような関数.~ テキストとスプレッドシート,どちらも読める.原則 FileType でどちらの形式なのかを指定する. #codeprettify(lang-matlab){{ datorg = readmatrix(filename, 'FileType', 'text', 'NumHeaderLines', 3, 'Delimiter', ','); }} NumHeaderLines や Delimiter を指定しなくても,ある程度判別してうまいことやってくれる場合もある.~ ただしミスを防ぐために可能な限り指定した方が良い.~ ~ 第2引数に以下の3つのいずれかのオブジェクトの変数を入れる方法もある.~ { SpreadsheetImportOptions | DelimitedtextImportOptions | FixedWidthImportOptions}~ これらは [[detectImportOptions>https://jp.mathworks.com/help/matlab/ref/detectimportoptions.html]] で取得可能.~ #codeprettify(lang-matlab){{ opts = detectImportOptions(filename); datorg = readmatrix(filename, opts); }} ~ ~ **readtable [#c7cc64dc] 文字列でも数値でも受け入れ可のため,readtable は dlmread よりも使い勝手が良い.~ ただしある程度フォーマットが整っていることが条件.~ #codeprettify(lang-matlab){{ tbl = readtable(filename,'HeaderLines',3,'Delimiter',','); % ヘッダー3行, csv の場合 }} ファイルのヘッダー情報が変数名と対応していない場合は,ReadVariableNames を false にする.~ 読んだ値は table 型の配列になる.~ table 型は 扱い方としては 数値(浮動小数点数 double など)の配列と cell 配列の間くらいの存在.~ 列ごとの変数名が定義されていれば, #codeprettify(lang-matlab){{ xyz = tbl(:,{'X','Y','Z'}); }} のように列番号を指定せずに列の変数名を指定して値を抜き出せる.~ また,読んだ後の table 配列を数値配列に変換するには,[[table2array>https://jp.mathworks.com/help/matlab/ref/table2array.html]] を使っても良いし, #codeprettify(lang-matlab){{ x = tbl.X; }} とすることもできる.~ ~ ~ **importdata [#r645e820] -文字列を含んだデータがある場合 #codeprettify(lang-matlab){{ dataorg = importdata(filename,DelimiterIn,HeaderlinesIn) }} この場合,dataorg は構造体となり,文字列を含んだデータ列と,数値のデータ列はそれぞれ, #codeprettify(lang-matlab){{ dataorg.textdata dataorg.data }} として格納される.~ importdata は文字列と数値が混在し,データ列数がバラバラでも一応読める場合がある.~ ただしその場合,文字列も数値も縦一列にデータが並んだりしてデータ抽出が困難.~ ~ ~ **textscan[#s0866568] -データ列数が統一されていないファイルなど,その他全て~ テキストと数値が混在するファイルは大抵 textscan になると思う.~ fopen で開いて,textscan で読み取って,fclose で閉じる.~ +FormatSpec で指定した形式で N 回分読む.~ ヘッダーが3行なら #codeprettify(lang-matlab){{ dataorg = textscan(fileID,FormatSpec,N,'HeaderLines',3); }} +FormatSpec で指定した形式で同じ format が続いているだけ,またはファイルの最後まで読む.~ #codeprettify(lang-matlab){{ dataorg = textscan(fileID,FormatSpec,'HeaderLines',3); }} +区切り文字(Delimiter)ごとに読む~ dlmread と同様,区切り文字が統一されていれば,FormatSpec にカンマ等を含めずとも #codeprettify(lang-matlab){{ dataorg = textscan(fileID,FormatSpec,'Delimiter',','); }} でOK.とりあえず1行ごとにテキストをまるっと読みたければ~ #codeprettify(lang-matlab){{ dataorg = textscan(fileID,FormatSpec,'Delimiter','\n'); }} ***FormatSpec のあれこれ [#e5dc02c5] Fortran によって #codeprettify(lang-fortran){{ !(注)Fortranのコード format(<nx>f10.3) !例① 固定長の数値がnx個分横に並ぶ format(<nx>(1pe12.3,",")) !例② 数値のみのcsv format(a,",",<nx>(f0.2,",")) !例③ 最初の列に文字列があるcsv }} という形式で出力されたファイルの場合,MATLAB の textscan では FormatSpec の部分を #codeprettify(lang-matlab){{ repmat('%10.3f',[1 nx]) % 例① repmat('%f,',[1 nx]) % 例② ['%s,',repmat('%f,',[1 nx])] % 例③ }} とする.~ csv ファイル等は,行末のカンマ(,)の有無によって FormatSpec の書き方が変わるので注意.下記参照.~ #codeprettify(lang-fortran){{ !(注)Fortranのコード format(<nx-1>(1pe12.3,","),1pe12.3) !例②' 行末カンマなし }} #codeprettify(lang-matlab){{ % MATLAB textscanのFormatSpec [repmat('%f,',[1 nx-1]),'%f\n'] % 例②' \nは無くても可 }} 文字列形式 '%s' は Delimiter を指定しないと,空白を勝手に区切りとして扱ってしまうためなかなか厄介. 空白の数がわかる場合や文字列の幅が決まっているときは指定する.~ 行の残りの部分を読み込まずに改行 '\n' までスキップする場合は, #codeprettify(lang-matlab){{ '%*[^\n]' % textscanではできるがfscanfではできない }} を付け加える.例えば,~ Time = 2.000000, X = 0.005, ...... というテキストの数値部分だけがほしい場合には, #codeprettify(lang-matlab){{ fmt = 'Time =%f,X =%f%*[^\n]'; % FormatSpec dataorg = textscan(fileID,fmt,1); % 1は1回実行する,の意 }} とする.~ ***テキストを読み込んだ後 [#yf42e4d1] textscan で FormatSpec の指定子が複数あればセル配列にとして格納される.数値データのみで行列形式になっていれば #codeprettify(lang-matlab){{ hoge = cell2mat(dataorg) }} でセル配列でない matrix データとなる.~ textscan は最も融通が利くが,FormatSpec の指定と cell からの変換操作が必要なので,dlmread で済むなら dlmread を使いたい.~ ~ ***注意 [#c72cc302] textscan は行頭から最初の文字までの空白を勝手に読み飛ばしてしまい,format 指定子に %c を使ってもその最初の空白は文字数としてはカウントされず無視される.~ 固定長出力のファイルには fscanf を使ったほうが良い. ~ ~ **fscanf [#d63503d3] -textscan と同様,自由形式ファイル~ こちらも fopen と fclose でファイルの開閉を行う.~ fscanf は,その時の読み取り位置が行末("\n"=改行コードの手前)なのか,行頭("\n"の次)なのかを把握しておくことが重要.~ textscan のように,FormatSpec に '%*[^\n]' を含めて次の改行位置までスキップすることはできない. #codeprettify(lang-matlab){{ hoge = fgetl(fid); }} を使うと,読み取り位置から次の改行位置まで hoge に text が格納されるので,ヘッダー行の回数分だけ実行すれば,読み飛ばすことができる.~ この時,読み取り開始位置が行末にあると,hoge には何も入らずに次の行頭に移動するだけになる.~ 上記 textscan で示した例②のフォーマットが縦に ny 行分あるとすると,以下のようにすることでデータ元の配列通りに読み込みが可能. #codeprettify(lang-matlab){{ fmt = repmat('%f,',[1 nx*ny]); fid = fopen(filename,'r'); dataorg = fscanf(fid,fmt,[nx ny])'; fclose(fid); }} ny 行 nx 列でも,"[nx ny]" となる点に注意.転置記号の操作によって ny 行 nx 列になっている.~ ~ ~ **参考 MathWorks公式 [#xfa50522] -[[dlmread>https://jp.mathworks.com/help/matlab/ref/dlmread.html]]~ -[[readmatrix>https://www.mathworks.com/help/matlab/ref/readmatrix.html]]~ -[[readtable>https://www.mathworks.com/help/matlab/ref/readtable.html]]~ -[[importdata>https://jp.mathworks.com/help/matlab/ref/importdata.html]]~ -[[textscan>https://jp.mathworks.com/help/matlab/ref/textscan.html]]~ -[[fscanf>https://jp.mathworks.com/help/matlab/ref/fscanf.html]]~