4.8: Logical Indexing with 2D Arrays
- Page ID
- 136626
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\dsum}{\displaystyle\sum\limits} \)
\( \newcommand{\dint}{\displaystyle\int\limits} \)
\( \newcommand{\dlim}{\displaystyle\lim\limits} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\(\newcommand{\longvect}{\overrightarrow}\)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\ket}[1]{\left| #1 \right>}\)
\(\newcommand{\bra}[1]{\left< #1 \right|}\)
\(\newcommand{\braket}[2]{\left< #1 \vphantom{#2} \right| \left. #2 \vphantom{#1} \right>}\)
\(\newcommand{\braopket}[3]{\left< #1 \vphantom{#2}\vphantom{#3} \right| #2 \vphantom{#1}\vphantom{#3} \left| #3 \vphantom{#1}\vphantom{#2} \right>}\)
\(\newcommand{\qmvec}[1]{\mathbf{\vec{#1}}}\)
\(\newcommand{\op}[1]{\hat{\mathbf{#1}}}\)
\(\newcommand{\expect}[1]{\langle #1 \rangle}\)
\(\newcommand{\dfn}[1]{\emph{\textbf{#1}}}\)
Logical indexing is not only useful for one-dimensional arrays. It also works with two-dimensional arrays, or matrices. This is very powerful because it allows us to select, count, replace, or analyze matrix elements based on a condition.
Recall that a logical expression returns values of either true or false. In MATLAB, true is often displayed as 1, and false is displayed as 0.
For example, suppose we have the following matrix:
A = [4 9 2; 7 1 8; 3 6 5];
If we write:
A > 5
MATLAB checks every element of A and returns a logical matrix:
0 1 0 1 0 1 0 1 0
This logical matrix tells us which elements of A are greater than 5.
The elements greater than 5 are:
9, 7, 8, and 6
To extract those values, we can use the logical condition as an index:
largeValues = A(A > 5)
The result is:
largeValues = [7; 9; 6; 8]
Notice that the result is returned as a column vector. MATLAB reads the matrix column by column when it extracts values using logical indexing.
This is important. Even though A is a 2D array, the extracted values are usually returned in a single column.
Replacing Invalid Sensor Readings
Logical indexing is often used to clean data. Suppose a temperature sensor records values in a matrix, where each row represents a different sensor and each column represents a different time.
In this example, the value 999 represents an invalid sensor reading. We can replace all invalid readings with NaN.
Solution
temps = [72 74 NaN 75;
70 NaN 73 74;
68 69 70 NaN]
This is much easier than searching through each row and column manually.
Counting Values Above a Limit
Suppose the following matrix stores stress values measured at several locations on a mechanical part:
stress = [120 135 150 142; 110 160 155 130; 125 145 170 138];
Assume that any stress value above 150 MPa is considered too high. We can find how many times the stress has reached above the limit.
Solution
highStress =
3×4 logical array
0 0 0 0
0 1 1 0
0 0 1 0
numHigh =
3
highStressValues =
160
155
170
This type of operation is very useful when checking whether experimental or simulation data exceeds a safe limit.
Replacing Values Below a Threshold
Suppose a grayscale image is stored as a matrix of pixel intensities. In many images, pixel values range from 0 to 255, where 0 represents black and 255 represents white.
imageData = [25 80 130;
45 160 210;
10 95 250];
Suppose we want to make all pixels below 100 completely black. We can write:
Solution
imageData =
0 0 130
0 160 210
0 0 250
This type of operation is useful in image processing because it allows us to modify many pixels at once based on a condition.
Replacing Values Below a Threshold
Sometimes one condition is not enough. We may want values that satisfy two conditions at the same time. Suppose we want to find values greater than 3 and less than 8 in an array.
Solution
values = 4 7 6 5
Important Note About Output Order
When logical indexing extracts values from a matrix, MATLAB returns the values in column-major order. This means MATLAB goes down the first column, then down the second column, then down the third column, and so on.
For example:
A = [4 9 2;
7 1 8;
3 6 5];
If we write:
A(A > 5)
MATLAB returns:
[7; 9; 6; 8]
This order may look surprising at first. The values greater than 5 appear in the matrix as 9, 7, 8, 6 if you read row by row. But MATLAB reads down columns first, so it returns 7, 9, 6, 8.
This does not mean MATLAB made a mistake. It is just using its normal column-by-column storage order.


