# Logical Indexing, NaN, Basic Plotting

## Contents

## Logical Operations

In addition to math operations, Matlab can also do logical comparisons:

```
2>1
2>7
1==2 %test equality
1==1
7<=9
9<=9
```

ans = 1 ans = 0 ans = 0 ans = 1 ans = 1 ans = 1

In Matlab, as in most programming languages `1` is true and `0` is false. (Technically, the commands `true` and `false` create logical variables, but Matlab is usually smart enough to convert back and forth when you need it to. If you ever get in a pinch, you can use the functions `logical` to convert numbers to True/False logicals and `double` to convert from logical to numerical.)

Just as importantly, we can also do operations like AND and OR:

1&1 %AND 1&0 1|0 %OR 0|0 %OR ~1 %NOT

ans = 1 ans = 0 ans = 1 ans = 0 ans = 0

And these work just as easily for vectors:

aa=rand(10,1); %create a 10x1 column vector of random numbers between 0 and 1 aa>0.5 bb=aa>0.5; %we can save this output cc=rand(10,1)>0.5; %cut out the middle man ee=(bb==cc) %tests equality element-wise (why isn't every entry 1?) bb|cc %short circuit OR

ans = 0 1 0 0 0 0 0 0 1 0 ee = 1 0 0 0 1 0 1 1 1 1 ans = 0 1 1 1 0 1 0 0 1 0

## Working with logicals

Some other tests we might find useful:

any(ee) %test if any of the elements in ee is nonzero all(ee) %test if all of the element in ee is nonzero

ans = 1 ans = 0

When dealing with logicals, we often want to get all the entries of an array where some condition is nonzero. To do this, we use the find command, which takes a logical array as an input and returns all the indices which are true (nonzero):

find(ee)

ans = 1 5 7 8 9 10

In fact, it's worth the time to look up find. It has many more useful options for more complicated problems, and using it well will become important to our programming later on.

## Logical Indexing

The most frequent use of logicals for us, however, will be in indexing. Logical indexing will allow us to select and manipulate only those subsets of data that satisfy particular logical conditions.

When we index an array with a logical variable, Matlab is using `find` to locate all the true elements and convert them to indices.

So for instance, if we create a 5x5 array of random integers from 1 to 50:

```
A=randi(50,5,5); %look this command up
```

we could grab a sub-block of it by using indices...

```
A(1:2,3:4) %remember this?
```

ans = 22 24 8 15

... or we could use indices stored in a variable.

submat=[1 2; 8 16]; A(submat)

ans = 3 7 26 24

But we could also use a logical array:

```
Aupper=A>=25 %true (1) if the entry in A is greater than or equal to 25, 0 otherwise
A(Aupper)
```

Aupper = 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 1 0 1 1 ans = 26 50 39 38 44 36 30

Note that Matlab gave us back every entry of `A` for which `Aupper` was true, but it did not give us back a result in matrix form. This happend for two reasons:

- There is no real way to arrange the returned values back into a matrix, since that matrix would have missing elements, and Matlab doesn't know what to do about that.
- Matlab is doing exactly what we asked it to do: return it the values of
`A`at certain indices (given by using`find`on`Aupper`). We get a vector back for the same reason that`A(1:20)`would have returned the first 20 elements in a vector: indexing this way ignores the matrix structure.

But if we only want to use logical indexing to *change* values inside a matrix, a really nice thing happens:

A(Aupper)=100

A = 3 2 22 24 100 7 16 8 15 1 1 100 100 21 2 10 20 100 22 12 4 100 5 100 100

returns a matrix!

Why? Because Matlab is assigning the value 100 to several elements of `A` (all those for which `Aupper` is true), but this assignment *does not* need to change the matrix structure. First (corresponding to the first reason above) because `A` still has all its elements. Second (as in the second reason) because we're not extracting data, just modifying it in place.

This type of manipulation becomes extremely powerful once you learn to use it well. Very, very often, we want to extract or change only those parts of an array that satisfy certain conditions, and logical indexing will be the method we choose to use. For more examples and elaboration, see the Indexing Cheatsheet

## The special values: Inf and NaN

In addition to numbers, Matlab arrays can store a couple of additional special values. One arises through some pathological arithmetic operations:

1/0 -1/0

ans = Inf ans = -Inf

This symbol behaves much as you'd think:

Inf + 2 Inf * 3 Inf / -1

ans = Inf ans = Inf ans = -Inf

Matlab also has special functions that allow us to test whether a variable or array element is infinite (and thus to `find` it and perhaps change it):

isinf(1/0) isfinite(1/0)

ans = 1 ans = 0

The other special symbol arises in cases where arithmetic operations not only aren't defined, they can't be extended using `Inf`:

0/0 Inf/Inf

ans = NaN ans = NaN

There's no real predicting how this symbol will act, so here are the rules:

NaN*1 NaN-1 NaN+NaN NaN+Inf

ans = NaN ans = NaN ans = NaN ans = NaN

In other words, you can't "undo" a NaN. On the other hand, |NaN|s have two big advantages:

- They serve as placeholders for missing or undefined data
- They don't show up on plots

The first property is really important when you may have different numbers of data points in different trials, but you need to store everything in a single array:

B=[5 7 9; 10 36 NaN; NaN NaN 4];

Typically, you'd code missing data as 0 or -1 or 999, but you don't want to use these values in an average. And Matlab has a shortcut for this:

```
mean(B) %mean down columns
```

ans = NaN NaN NaN

Ugh... but

```
nanmean(B) %works just fine
```

ans = 7.5000 21.5000 6.5000

The second property can be illustrated with a simple plot:

t_axis=0:0.01:10; %define a time axis from 0 to 10 with points every 0.01 y=t_axis+2*sin(2*pi*t_axis)+0.5*randn(size(t_axis)); %look up the commands you don't recognize

And we can plot the data in `y` as a function of `t_axis`:

plot(t_axis,y)

But maybe we believe some data are corrupted, in which case we can replace them with |NaN|s.

bad=(t_axis>=4)&(t_axis<=5); y(bad)=NaN;

When we plot the modified version of `y` the `NaN` data points don't plot.

plot(t_axis,y)