前回はswitch文について説明しました。今回は、配列の操作について説明します。
配列から条件を満たす値を抽出する
配列の操作で頻繁に使用するテクニック「配列から条件を満たす値を抽出する」方法をご紹介します。if文 | MATLAB基礎で紹介した関係演算子を使用することで配列から目的の値のみ抽出することができます。
下記の図のようにあるデータの決められた範囲だけ切り取りたい場合、1行で記述することができます。この記事ではその書き方と内容の解説を行います。

配列から目的の値だけ抽出する例
データの生成
まずはいつも通りスクリプトファイルを準備して配列を作成します。時系列データを扱う際によく用いられる、1列目がタイムスタンプ、2列目がデータという形式の行列を作成します。
f = 1;%周波数[Hz]
omega = 2*pi*f;%角周波数[rad/s]
Data(:,1) = transpose(0:0.01:10);%timestamp
Data(:,2) = sin(omega * Data(:,1));上の例では、1列目がタイムスタンプ(0から0.01sec間隔で10secまで)、2列目がデータ(sin(ωt))としたDataという行列を作成しました。
データの確認
生成したデータを確認するため、グラフを作成します。下記コードを実行しグラフを生成します。
figure(1)
plot(Data(:,1),Data(:,2))
グラフを確認すると、0~10secまで1Hzのsinカーブが生成されていることがわかります。
決められた時刻のデータを抽出する
早速生成したデータから値を抽出します。まずは特定の時間の値を抽出します。例えば3sec以降の値を抽出するコードは下記のとおりです。
Data_after_3 = Data(Data(:,1)>=3,:);抽出した配列を確認するため、下記コードでグラフを作成します。
figure(2)
plot(Data_after_3(:,1),Data_after_3(:,2))
xlim([0 10])
意図通りの3sec以降のデータを抽出できたことがグラフから確認できます。
値抽出の説明
上の例で3sec以降の値を抽出したコードの説明をします。そのために下記コードを実行します。
Idx = Data(:,1)>=3;上記のコードはData(:,1)でDataという行列の1列目(タイムスタンプ)を抽出しています。そして抽出した値が3以上かどうか関係演算子で比較しています。(行列からデータを抽出する方法に関しては、行列の操作 | MATLAB基礎7を、関係演算子についてはif文 | MATLAB基礎14を参考にしてください。)
上のコードはタイムスタンプが3以上なら「1」そうでなければ「0」となるベクトルIdxを作成しているということになります。
ワークスペースで、Idxをダブルクリックし中身を確認することができます(下図参照)。

Data(:,1) >= 3を満たすのは3sec以降なので、Idxの301行目以降の値が「1」、0~300番目は「0」のベクトルが生成されています。またワークスペースのIdxの右隣に「1001×1 logical」という記載があります。これは1001行1列のベクトルで、変数がlogicalという型であることを示しています。
ここで「型」について詳細の解説は行いませんが、logicalという型は1が真(True)、0が偽(False)を表します。Idxという変数は、「1」と「0」からなるlogical型のベクトルであることを示しています。
logical配列で値抽出
MATLABでは行列やベクトルと同サイズlogical配列を用いて対応するlogical配列が1のデータを抽出することができます。先ほどの例でいうと、下記のようなコードを記述すると、Data行列からIdx行列が1の部分だけ値を抽出できます。
Data(Idx,1)もちろん1列目と2列目の両方の値を抽出したいので上のコードを下記のように変更します。
Data(Idx,:)こうすることでData行列でIdxが1となるすべての列の値を取得できます。この値をData_after_3に代入するコードは下記のとおりです。
Data_after_3 = Data(Idx,:);上のIdxは「値抽出の説明」で記述したコード(Idx = Data(:,1)>=3;)に置き換えることができるので、最終的に下記コードで3sec以降の値を取得することができます。
Data_after_3 = Data(Data(:,1)>=3,:);色々と説明しましたが、慣れてしまえば特に意識せず使用することができるます。
値抽出の応用
少し応用についても説明します。例えば3sec以降7sec未満のデータを抽出したい場合は下記の記述になります。併せてグラフも作成します。
Data_3_7 = Data(Data(:,1)>=3 & Data(:,1)<7,:);
figure(3)
plot(Data_3_7(:,1),Data_3_7(:,2))
xlim([0 10])
上の例では2つの関係演算子と1つの論理演算子を組み合わせています。「3sec以上」と「7sec未満」のAND(両方を満たす)場合の値を取得しています。
グラフでも3sec~7secまでのデータが抽出できていることがわかります。
データから値を選択
これまでの例では1列目のタイムスタンプを用いて値を抽出しましたが、2列目のデータを用いて値を抽出することも可能です。例えば、正のデータのみを抽出するコードは下記の通りです。
Data_positive = Data(Data(:,2)>=0,:);
figure(4)
plot(Data_positive(:,1),Data_positive(:,2))
xlim([0 10])
ylim([-1 1])Data(:,2)>=0として、Data配列の2列目の値に対して関係演算子を使用している点が先ほどと異なる点です。

グラフから正の値のみ抽出できていることがわかります。サンプルの都合上0付近の値の連続性があまりよくありませんが問題ありません。タイムスタンプの間隔を小さくすれば解決します。
特定のデータのみ処理を加える
もう少し応用として、例えばDataの負の値のみ正にの値になるように処理を加えることにします。
Data(Data(:,2)<0,2) = -Data(Data(:,2)<0,2);
figure(5)
plot(Data(:,1),Data(:,2))
xlim([0 10])
ylim([-1 1])上の例ではData配列の2列目が0より小さい場合、マイナスをかける処理を実施しています。さらに、元のData配列のData配列の2列目が0より小さい値に代入しなおしています。つまりマイナスの値がすべてプラスの値に変換されることになります。

生成したグラフを確認するとすべて正の値になっていることがわかります。
配列の絶対値をとる関数でabsがあります。abs関数を用いるともっと簡素に記述できますが、今回は説明のため使用しませんでした。興味のある方は、absを使用した処理方法にもチャレンジしてください。
まとめ
今回は配列から値を抽出するテクニックをご紹介しました。配列から特定のデータを抽出することは非常に頻繫に行う作業なので、使いこなせるようになりましょう。
次回はbreak, continueについて説明します。
本日作成したコードを載せておきますので、適宜ご活用ください。またabs関数を使用した例も下記に記載しましたので、答え合わせに活用してください。
f = 1;%周波数[Hz]
omega = 2*pi*f;%角周波数[rad/s]
Data(:,1) = transpose(0:0.01:10);%timestamp
Data(:,2) = sin(omega * Data(:,1));
figure(1)
plot(Data(:,1),Data(:,2))
Data_after_3 = Data(Data(:,1)>=3,:);
figure(2)
plot(Data_after_3(:,1),Data_after_3(:,2))
xlim([0 10])
Data_3_7 = Data(Data(:,1)>=3 & Data(:,1)<7,:);
figure(3)
plot(Data_3_7(:,1),Data_3_7(:,2))
xlim([0 10])
Data_positive = Data(Data(:,2)>=0,:);
figure(4)
plot(Data_positive(:,1),Data_positive(:,2))
xlim([0 10])
ylim([-1 1])
Data(Data(:,2)<0,2) = -Data(Data(:,2)<0,2);
figure(5)
plot(Data(:,1),Data(:,2))
xlim([0 10])
ylim([-1 1])
Data_abs = abs(Data(:,2));
figure(6)
plot(Data(:,1),Data_abs)
xlim([0 10])
ylim([-1 1])
コメント