Loren on the Art of MATLAB

Turn ideas into MATLAB

Note

Loren on the Art of MATLAB has been archived and will not be updated.

Get Smart, Be Logical!

Recently a customer asked me an interesting question about a good way to compute something. Before I sat down to tackle it, I happened to mention the problem to my pal, Sean. And he quickly answered, "max logical". It took me just a moment to realize what he was saying, and it is the answer to the problem. But when I heard it, I heard a person's name "Max Logical", and though I didn't know who that was, I immediately thought of Maxwell Smart, from the 60s tv comedy in the US, called "Get Smart". By General Artists Corporation-GAC-management. [Public domain], via Wikimedia Commons And you can see the precursor to today's mobile phones!

Contents

The Problem

So what's the problem? The customer posed it by way of an example. Given a 3-D array A, generated for this example from a matrix, find the first plane in which some condition is true.
A=[1 2; 3 4]
M = cat(3, A, A+1, A+2, A+3);
A =
     1     2
     3     4
So the function should work like this: IDX = someFunction(M >=5);
IDX = [NaN 4; 3 2]
IDX =
   NaN     4
     3     2
And, the customer wanted this to work for arrays of higher dimensions as well.

The Solution

As I said, I mentioned this to Sean. But I had thought for about 2 seconds about it before and I realized I could do a find on the entire array, as if it were a vector, get the locations and sort them into their proper locations and find the first one in the correct last dimension. And then Sean said "Max Logical". Here's what a great solution looks like.
catdim = 3;
szA = size(A);
[mv,midx] = max(M >= 5,[],catdim);
IDX = NaN(szA);
IDX(mv) = midx(mv)
IDX =
   NaN     4
     3     2
Why/how did this work? Well, I use the condition I want met into function max, and it is logical input, meaning only 0s and 1s. And max returns the index where the first condition is met, and I do this along the final dimension. Then create an array of NaN values, and use logical indexing to update this index matrix. Voila!

Higher Dimensions

Now let's see if it makes sense in higher dimensions. For simplicity, I again will provide a base array in 1 dimension less than I am ultimately looking, so I can construct something for which I can reasonably easily check the result.
A = randi(17, [3 2 1 3]);
catdim = ndims(A)+1
M = cat(catdim, A, A+1, A+2, A+3, A+4);
catdim =
     5
See a slice of M
sliceOfM = M(:,:,:,1)
sliceOfM =
    12     2
    13     4
     8    16
Apply the max, logical indexing to M next.
szA = size(A)
[mv,midx] = max(M >= 13,[],catdim);
IDX = NaN(szA);
IDX(mv) = midx(mv)
szA =
     3     2     1     3
IDX(:,:,1,1) =
     2   NaN
     1   NaN
   NaN     1
IDX(:,:,1,2) =
   NaN     1
     1   NaN
     4   NaN
IDX(:,:,1,3) =
   NaN     1
     1     1
   NaN     1

Have You Embraced Logical Indexing?

I have made several posts over the years on indexing that readers have found helpful. Do you have any interesting logical stories to share? Post them here.

Published with MATLAB® R2017b

  • print

コメント

コメントを残すには、ここ をクリックして MathWorks アカウントにサインインするか新しい MathWorks アカウントを作成します。