2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Matlabの基礎

Posted at

はじめに

新しい会社に入ったらMatlabをやることになったので、自分用のまとめです。
行列、セル行列、containers.Map、tableなどの編集・参照方法をまとめます。
なお、現状会社で使用するのは2021年バージョンなので、それ以降の機能(dictionaryなど)は含みません。

行列

行列は縦と横に数や記号を並べたものです。
行列内のデータはすべて同じ型でなければなりません。

行ベクトル(1行n列)

A=[1 2 0 4 5]    % 初期化
B = 1:1:5  % 初期化
A(3) = 3         %代入(編集)
C = A(2:4)       %抽出
D = A + B        %加算
E = A - B        %減算
F = A .* B       %アダマール積
G = A ./ B       %アダマール除算
H = [A B C]           %連結
I = horzcat(A, B, C)  %連結(上と同じ)

image.png

列ベクトル(n行1列)

A=[1; 2; 0; 4; 5;]    % 初期化
B = (1:1:5)'     % 初期化(行ベクトルを転地)
A(3) = 3         %代入(編集)
C = A(2:4)       %抽出
D = A + B        %加算
E = A - B        %減算
F = A .* B       %アダマール積
G = A ./ B       %アダマール除算
H = [A; B; C]         %連結
I = vertcat(A, B, D)  %連結(上と同じ)
J = horzcat(A, B, D)  %行方向に連結

image.png

行列(n行m列)

A = [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12] % 初期化(4行3列)
B = rand(4, 3)  % ランダム初期化(4行3列)
C = rand(3, 4)  % ランダム初期化(3行4列)
D = A + B         % 加算(A+Cはエラー)
E = A - B         % 減算(A-Cはエラー)
F = A .* B        % アムダール積(A.*Cはエラー)
G = A ./ B        % アムダール除算(A./Cはエラー)
H = A / B         % 除算(A/Cはエラー)
I = H * B         % Aと一致
J = A * C         % 積(A*Bはエラー)
K = A + 3         % すべての要素に3を加算(その他四則演算も同様)

image.png

行列上での文字列

A=['a', 'b', 'c';'c', 'd', 'e'; 'f', 'g', 'h']
B=["a", "b", "c";"c", "d", "e"; "f", "g", "h"]

''だとchar配列。
""だとstring(文字列)。
行列にいれると違いが明確にわかる。
image.png
char配列だと行ベクトルとして合算されるが、文字列だと単一の値として扱われる

A=['a', 'bc', 'c';'c', 'd', 'e'; 'f', 'g', 'h']   %こちらはエラー
B=["a", "bc", "c";"c", "d", "e"; "f", "g", "h"]   %こちらは問題なし

image.png

行列から抽出

A = [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12] % 初期化(4行3列)
A(2)          % ans => 4(行方向に最初に進むらしい)
A(11)         % ans => 9(行方向に最初に進むらしい)
A(3,2)        % ans => 8(3行2列目)
A(2:3, 2)     % 2行目から3行目の2列目を抽出
A(:, 2:3)     % すべての行に対して、2列目から3列目を抽出
A(1:2:4, 3)   % 1行目から4行目まで2行おきに、3列目を抽出

image.png

特定の数値に一致した行/列から値を抽出する

A = [1 2 3 ;...
     4 5 6 ;...
     7 8 9]

%『3』がある行から2列目を抽出する     
resultA = A(any(A == 3,2) , 2)
% 同じ場所に222を代入する
A(any(A == 3,2) , 2) = 222

%『3』がある列から2行目を抽出する    
resultB = A(2 , any(A == 3,1))
% 同じ場所に666を代入する
A(2 , any(A == 3,1)) = 666

% 上記の補足
% 2を指定すると行方向に探索する。つまり1行目だけが1の列ベクトルがとれる
any(A == 3,2)

% 1を指定すると列方向を探索する。つまり3列目だけが1の行ベクトルがとれる
any(A == 3,1)

image.png

セル配列

普通の行列だと同じ型しかいれることができなかったが、セル配列を利用すると様々な型を同時に扱うことができる。印象としては、普通の行列は配列に値を直接入れたもの。セル行列は配列に、C言語でいうところのポインタを入れたもの。

% セル配列の定義
A = {1, 'abc', 1.234; ...
     "ABC", pi, -100;...
     0, "" , 5.1}
    
% セル配列の抽出(Bもセル配列になる)
B=A(2:3, 1:2)
% 次の方法だと先頭要素だけがCに入る(多分使わないほうがいい)
C=A{2:3, 1:2}

% 次の代入方法ではエラーになる
%A(1, 3) = '3' 
% 以下の方法なら成功する(1行3列目に代入)
A{1, 3} = 4.321

image.png

セル配列内の特定の要素だけを抽出

A = {1, 'abc', 1.234; ...
     "ABC", pi, -999;...
     0, "" , 5.1}

% 文字列だけを取得(char配列は対象外)
idx = find(cellfun(@(x) isstring(x) , A)) 
B = A(idx)

% ABCという文字がある行の3列目を取得
idx = find(cellfun(@(x) isstring(x) && strcmpi(x, "ABC") , A)) 
C = A(idx, 3)


image.png

セル配列の連結

行列と同じく、vertcatおよびhorzcatで問題ない

D = vertcat(A , {"abc", "aaa", "zzz"}) % 縦(行方向)に追加
E = horzcat(A , {"abc"; "aaa"; "zzz"}) % 横(列方向)に追加

image.png

セル配列から行列へ変換

すべてが数値やchar配列なら以下のように変換できる

A = {1 2 3 ;...
     4 5 6 ;...
     7 8 9};
B = cell2mat(A)

C = {'a' 'b' 'c' ;...
     'd' 'e' 'f' ;...
     'g' 'h' 'i'}
D = cell2mat(C)

image.png

stringの場合はなぜかできない


A = {"a" "b" "c" ;...
     "d" "e" "f" ;...
     "g" "h" "i"}
     
B= ["a" "b" "c" ;...
     "d" "e" "f" ;...
     "g" "h" "i"]
     
% AをBのように変換したいのにエラーとなる
C = cell2mat(A{:})

image.png

string型のセル配列を行列に変換したい場合は次のようにする

A = {"a" "b" "c" ;...
     "d" "e" "f" ;...
     "g" "h" "i"}
     
C = string(A)

image.png

containers.Map

C++で言うところのstd::mapと同じものだと思う。
なお、R2022年度からdicrionaryが使えるそうだが、違いはkeyに利用できる型がMapは文字列かスカラー値だけだが、dictionaryはイミュータブルなオブジェクトでも使えること、メソッドが増えていること、パフォーマンスもいいことが挙げられるが使ったことがないので詳細は知らない。

A = {'a' 'b' 'c' ;...
     'd' 'e' 'f' ;...
     'g' 'h' 'i'}
B = [1 2 3; 4 5 6; 7 8 9]
C = containers.Map(A, B)   % Mapの初期化(key:A, value:B)
D = containers.Map(B, A)   % Mapの初期化(key:B, value:A)

% 注意点として、Mapのkey, valuesはともにcell配列になっている
E = D.keys
E = D.values


% cell配列なので{}でくくらないと動かない
% F = C(E(1)) % これはエラーになる 
F = C(E{1})    % こちらは成功する

C(E{1})  = 111 % 代入はこれでOK
C(E{1}) 

% keyがあるかどうかの確認
isKey(C, 'a')
isKey(C, 'z')

% 要素追加(型を一致させる必要あり)
C('z') = 3; % 型が一致しているので問題なし
D(10) = 3; % 型が不一致のためエラーとなる

image.png

table

names = {'Alice'; 'Bob'; 'Charlie'};
ages = {25; 30; 28};
heights = [1.65; 1.80; 1.75];
columns = {'Name', 'Age', 'Height'}

% table初期化
T = table(names, ages, heights, 'VariableNames', columns)

% 参照はカラム名からでも列数からでも可能
A = T{1:2, 'Name'}
B = T{1:2, 1}

% 次の方法ですべてのHeight要素に1を加算
T.Height = T.Height+1

% ひとつだけ変更したい場合は以下のようにする
T.Height(2) = T.Height(2) + 1

% ただし、セル配列はエラーとなる
T.Age = T.Age + 1

image.png

talbe内のセル配列の変更

% セル配列なのでcellfunを適用し、それを直接代入する
% num2cell()がないとセル配列でなくなるので、セル配列を維持したいならこれをつける
T.Age = num2cell(cellfun(@(x) x+1 , T.Age ))

image.png

Table内の特定の要素を抽出する

% Heightが2.7以上のNameを抽出する(行列なら以下で問題ない)
H = T(T.Height > 2.7, :).Name
% セル配列だと同じやり方でエラーとなる
A = T(T.Age > 25, :).Name

image.png

Table内の特定の要素を抽出する(セル配列内を検索)

% セル配列なのでcellfunを使用する
% Ageが25以上のNameを抽出したいとき
T.Name{find(cellfun(@(x) x > 25 , T.Age ))}

image.png

Table内を変更したい時

% Heightが2.7以上の名前を変更する
% ただし、この場合は見つかった要素が2つであることが予めわかっていたからできた書き方
T(T.Height > 2.7, :).Name = {'abc';'def'}

% 見つかった最初の要素だけを変更する
T(T.Height > 2.7, :).Name{1} = 'ABC'

image.png

Table内のある文字列に一致した要素の行の一部を編集したいとき

% Nameが"ABC"のAgeを99に変更する(抽出は=99を削除すればOK)
T.Age{find(cellfun(@(x) strcmpi(x, "ABC") , T.Name ))} =99

終わりに

Matlabの行列式やセル行列を実際に編集しようとした時、あまりにもできなかったので勉強のつもりで記事を書きました。あくまでも自身の勉強のためなので、わかりやすく書いてはいませんが、だれかの参考に少しでもなれば幸いです。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?