技術情報

MathWorks インサイト

MATLAB での行列インデックス付け


著者:

  • Steve Eddins, MathWorks
  • Loren Shure, MathWorks

この記事は8分で読めます

行列のインデックス付けとは、行列から一部の要素を選択したり変更したりする方法です。MATLAB® には、強力で柔軟なだけでなく、読みやすく表現力にも優れた複数のインデックス付け方法があります。行列は、MATLAB でデータを整理および解析するための中核的な要素であり、行列をわかりやすく効果的に操作するうえで、インデックス付けが重要な役割を果たします。

インデックス付けは、MATLAB ユーザーがよく耳にするもう 1 つの用語、ベクトル化と密接に関係しています。ベクトル化とは、スカラー演算の代わりに MATLAB の行列演算やベクトル演算を使用することです。通常、コードがより短くなり、数学的な表現力と可読性が向上し、場合によっては実行速度も向上します。

ベクトルのインデックス付け

最初に、ベクトルと添字を使用する簡単なケースを見てみましょう。

 v = [16 5 9 4 2 11 7 14];

添字には単一の値を指定できます。

 v(3) % Extract the third element
 ans =
 9

また、添字自体を別のベクトルにすることもできます。

 v([1 5 6]) % Extract the first, fifth, and sixth elements
 ans =
 16 2 11

MATLAB のコロン表記を使用すると、v から一定範囲の要素を簡単に抽出できます。

 v(3:7) % Extract the third through the seventh elements
 ans =
 9 4 2 11 7

v の前半と後半を入れ替えて、新しいベクトルを作成します。

 v2 = v([5:8 1:4]) % Extract and swap the halves of v
 v2 =
 2 11 7 14 16 5 9 4

特殊な end 演算子を使用すると、v の最後の要素を簡潔に参照できます。

 v(end) % Extract the last element
 ans =
 14

end 演算子は範囲指定にも使用できます。

 v(5:end) % Extract the fifth through the last elements
 ans =
 2 11 7 14

end を使用して算術演算を行うこともできます。

 v(2:end-1) % Extract the second through the next-to-last elements
 ans =
 5 9 4 2 11 7

コロン演算子と end を組み合わせることで、k 個おきの要素を抽出したり、ベクトル全体の順序を反転したりするなど、さまざまな操作を実行できます。

 v(1:2:end) % Extract all the odd elements
 ans =
 16 9 2 7
 v(end:-1:1) % Reverse the order of elements
 ans =
 14 7 11 2 4 9 5 16

等号の左辺にインデックス式を使用すると、ベクトルの特定の要素を置き換えることができます。

 v([2 3 4]) = [10 15 20] % Replace some elements of v
 v =
 16 10 15 20 2 11 7 14

通常、右辺の要素数は、左辺のインデックス式で参照される要素数と同じでなければなりません。ただし、右辺にはスカラーを使用できます。これはスカラー拡張と呼ばれます。

 v([2 3]) = 30 % Replace second and third elements by 30
 v =
 16 30 30 20 2 11 7 14

注意: MATLAB では 1 ベースのインデックス付けを使用します。行列へのインデックス付けでは、0 から始める言語もあります。一方、MATLAB のように 1 から始める言語もあります。MATLAB では、数学の教科書でよく見られる表記法を採用しています。なぜ MATLAB は 1 から始まるのでしょうか。MATLAB の創設者である Cleve Moler は、「数学ではそうするからです」と説明しています。

2 つの添字による行列のインデックス付け

次に、行列へのインデックス付けについて考えてみましょう。ここでは、例として魔方陣を使用します。

 A = magic(4)
 A =
 16 2 3 13
 5 11 10 8
 9 7 6 12
 4 14 15 1

行列のインデックス付けでは、多くの場合 2 つの添字を使用します。1 つ目の添字が行、2 つ目の添字が列を表します。

最も単純な形式では、1 つの要素を取り出します。

 A(2,4) % Extract the element in row 2, column 4
 ans =
 8

より一般的には、一方または両方の添字をベクトルにすることができます。

 A(2:4,1:2)
 ans =
 5 11
 9 7
 4 14

添字の位置に単独で指定した「:」は 1:end の省略表記で、行全体または列全体を選択する際によく使用されます。

 A(3,:) % Extract third row
 ans =
 9 7 6 12
 A(:,end) % Extract last column
 ans =
 13 
 8
 12
 1

行列内に点在する要素をどのように選択するかは、混乱しやすい点です。たとえば、A から (2,1)、(3,2)、(4,4) の要素を抽出するとします。

行列内の離れた位置に点在する 3 つの値が強調表示された 4 行 4 列の行列。それぞれ、2 行 1 列、3 行 2 列、4 行 4 列にあります。

行列内に点在する要素。
この目的の出力はどのように表記すればよいでしょうか。

式 A([2 3 4], [1 2 4]) では、期待する結果は得られません。この図は、2 つの添字によるインデックス付けの仕組みを示しています。

行列内に点在する要素を抽出するには、別のインデックス付け方法が必要です。そこで、次のトピックに進みます。

線形インデックス付け

この式 A(14) はどのような処理を行うのでしょうか。

添字を 1 つだけ使用して行列 A にインデックス付けを行うと、MATLAB は、各列を上から下へ順番にたどり、A の要素が 1 つの長い列ベクトルに並べられているものとして扱います。次のようになります。

16
5
9
...
8
12
1

ヒント: MATLAB は列優先です。線形インデックス付けでは、各列を上から下へ順番にたどります。

式 A(14) は、この暗黙的な列ベクトルの 14 番目の要素を単純に抽出します。このように 1 つの添字で行列へのインデックス付けを行う方法は、一般に線形インデックス付けと呼ばれます。

各行列要素の左上に線形インデックスを示した図を見ると、A(14) が A(2,4) と同じであることがわかります。

単一の添字には、次のように複数の線形インデックスを含むベクトルを指定できます。

 A([6 12 15])
 ans =
 11 15 12

ここで、A の (2,1)、(3,2)、(4,4) の要素だけを抽出する問題をもう一度考えてみます。これらの要素は、線形インデックス付けを使用して抽出できます。

 A([2 7 16])
 ans =
 5 7 1

この例では簡単にわかりますが、一般的には線形インデックスをどのように計算すればよいのでしょうか。MATLAB には、行と列の添字を線形インデックスに変換する sub2ind という関数があります。これを使用すると、次のように目的の要素を抽出できます。

 idx = sub2ind(size(A), [2 3 4], [1 2 4])
 ans =
 2 7 16
 A(idx)
 ans =
 5 7 1

論理インデックス付け

インデックス付けのもう 1 つの形式である論理インデックス付けは、コンパクトかつ表現力に優れた記法であり、画像処理をはじめとする多くの用途で役立ちます。論理インデックス付けでは、行列の添字として 1 つの logical 配列を使用します。

使用できる logical 配列の例を次に示します。

A > 12 

ans =
4×4 logical array

1  0  0  1
0  0  0  0
0  0  0  0
0  1  1  0

これらは、論理式が true になる行列内の位置を示しています。この例では、値が 12 より大きいすべての位置が該当します。

ここで式 A(A > 12) を使用すると、logical 配列内の非ゼロ値に対応する行列要素が抽出されます。出力は常に列ベクトルの形式になります。

A(A > 12) 

ans =

 16
 14
 15
 13 

is で始まる MATLAB 関数の多くは logical 配列を返すため、論理インデックス付けに非常に役立ちます。たとえば、isnan、論理インデックス付け、スカラー拡張を組み合わせると、わずか 1 行のコードで配列内のすべての NaN 要素を別の値に置き換えることができます。

 B(isnan(B)) = 0

MATLAB には、contains、startsWith、matches など、logical 配列を返す string 配列用の関数が多数あります。これらを使用すると、論理インデックス付けによってテキストを操作できます。たとえば、「Skylab」を含む宇宙計画の名前をすべて抽出できます。

>> names

names =

  6×1 string array

    "Mercury"
    "Gemini"
    "Apollo"
    "Skylab"
    "Skylab B"
    "ISS"

>> names(contains(names,"Skylab"))

ans =

  2×1 string array

    "Skylab"
    "Skylab B"

論理インデックス付けは find 関数と密接に関係しています。式 A(A > 5) は、A(find(A > 5)) と等価です。単純なケースでは論理インデックス式の方が高速ですが、計算の別の処理でインデックス値が必要な場合は find を使用することがあります。たとえば、NaN 値を一時的にゼロに置き換えて何らかの計算を行い、その後 NaN 値を元の位置に戻す場合を考えます。この例の計算は、filter2 を使用した 2 次元フィルター処理です。次のように実行します。

 nan_locations = find(isnan(A)); 

 A(nan_locations) = 0; 

 A = filter2(ones(3,3), A); 

 A(nan_locations) = NaN; 

この記事で紹介した例を通じて、アルゴリズムをコンパクトかつ効率的に表現する方法の感覚をつかんでいただければ幸いです。こうした手法や関連関数を MATLAB プログラミングの選択肢に加えることで、簡潔で読みやすく、ベクトル化されたコードを作成する力をさらに高めることができます。

公開年 2024


使用製品: MATLAB

さらに詳しく