MATLABでフォルダ内の任意のファイルだけを解析して解析結果を保存するスクリプト


メモ書きです.読者はMATLAB初心者を想定しています.

ディレクトリ内に複数の解析対象matファイルといくつかの解析対象外のデータがある場合を想定します.解析対象matファイルにはそれぞれ同様な変数名とデータが格納されているものとします.
目的は ディレクトリ内の解析対象のファイルを読み込み,特定の解析を行い,解析結果を一つのmatファイルに保存する処理 を作成することです.

手順

  1. 一つのファイルに対して解析を行うスクリプトを作成する
  2. 手順1のスクリプトを関数化する
  3. フォルダ内の解析対象ファイルに対して手順2の関数を順に適応していくスクリプトを作成する
  4. 手順3のスクリプトを実行する

サンプルコードについて

以下のスクリプトを実行するとテスト用データをカレントディレクトリ内に生成することができます.以下のサンプルコードはこのコードで生成されたデータを想定して書かれています.

makeSampleFile.m
for i = 1:10
    Data = rand(1,100);
    save(['File', num2str(i),'.mat'], 'Data')
end

手順1

解析を行うスクリプトを作成する.
一般的に次のような流れになります.

  • データ読み込み
  • 解析
  • 解析結果出力
    • グラフ出力
    • コマンドウィンドウ出力
  • 解析結果保存

ひとまず,ひとつのデータだけ読み込み,正しく解析できるかどうか確認をしましょう.
解析がうまくいっているかどうか可視化手段を駆使して丁寧に確認することが重要です.一つずつ確実なコードを積み上げていかなければ,数百行と長大なコードとなった際にバグの特定に苦労することになります.
以下のサンプルコードでは平均と標準偏差という極々単純な計算を行っています.すべて電卓で検算するのはやり過ぎだとしても,その計算結果の数値が妥当なものなのか(平均値の計算結果が入力値よりも大きくなってないか否か...など)確認する程度のことは事あるごとにやっておきましょう.

samplescript.m
% データの選択
Filename = uigetfile;

% データの読み込み
load(Filename)

% データの解析
Std = std(Data);
Mean = mean(Data);

% データの可視化
figure;
plot(Data)

fprintf('標準偏差:%f\t平均:%f\n', Std, Mean)

% 解析結果の保存
save('result.mat', 'Std', 'Mean')

手順2

手順1のスクリプトを関数化する

手順1で作成したプログラムにおいて,解析結果出力に該当する部分と結果保存に該当する部分をコメントアウトします.
関数の引数には読み込むファイル名が格納される変数を,返り値には解析結果が格納される変数にします.

sampleFunction.m
function [Std, Mean] = sampleFunction(Filename)
% 指定されたファイルを読み込み,ファイルに格納されているデータの標準偏差と平均を返す関数
% 
% 引数:
%   Filename:読み込むデータのファイル名(str)
% 返り値:
%   Std     :データの標準偏差
%   Mean    :データの平均
% 

% データの選択
% Filename = uigetfile;

% データの読み込み
load(Filename)

% データの解析
Std = std(Data);
Mean = mean(Data);

% データの可視化
% figure;
% plot(Data)
% 
% fprintf('標準偏差:%f\t平均:%f\n', Std, Mean)

% 解析結果の保存
% save('result.mat', 'Std', 'Mean')

end

手順3

フォルダ内の解析対象ファイルに対して手順2の関数を順に適応していくバッチ処理スクリプトを作成する

以下のスクリプトを参考にしてください.

正規表現についてはこちらの公式ドキュメンテーションを参考にしてください.
正規表現 - MATLAB & Simulink - MathWorks 日本

sampleBatch.m
% 処理対象のディレクトリ指定
TargetDirectory = uigetdir;

% ディレクトリの内容を取得
DirectoryInfo = what(TargetDirectory);

% ディレクトリ内で処理対象のデータの正規表現を指定
Expression = 'File';

% 正規表現をもとにディレクトリ内で該当するファイルのラベルを取得
ExpSearchRes = regexp(DirectoryInfo.mat, Expression);
isTargetFile = cellfun(@isempty, ExpSearchRes);

% 処理結果を連番で保存するためのカウンター
Counter = 0;

% 構造体配列の宣言
Result = struct();

% ファイル名に関連付けられたラベルを順に見ていく
for i = 1:length(isTargetFile)
    % 解析対象ではないファイルの場合は飛ばす
    if isTargetFile(i)
        continue
    end

    % 解析対象のファイルの場合
    % 構造体配列用のカウンタを増やす
    Counter = Counter +1;

    % 手順2で作成した関数にファイル名を渡して解析する.
    [Std, Mean] = sampleFunction(DirectoryInfo.mat{i});

    % 結果を構造体配列に格納
    Result(i).Std = Std;
    Result(i).Mean = Mean;
    Result(i).FileName = DirectoryInfo.mat{i};
end

% 解析結果を保存する
save('Result.mat','Result')

手順4

手順3のスクリプトを実行する

こんな感じの構造体配列が生成されると思います.

Std Mean FileName
0.2790 0.5142 'File1.mat'
0.3114 0.4991 'File10.mat'
0.3203 0.5300 'File2.mat'
0.2913 0.5542 'File3.mat'
.... ... ...

解析対象のファイルの中に異常なデータがある場合はエラーを吐いて処理が停止してしまう場合もあります.
これを避けるにはtry ~ catch文を使用するとよいです.
ただエラーを無視して処理が進んでしまうので,デバッグ時には使わないでおきましょう.