1
m  = randi([1 4],4,4)

I'd like to create separate binary matrices for each unique integer:

mm{1} = m==1
mm{2} = m==2
mm{3} = m==3
mm{4} = m==4

With four different integers the above is fine, but my original matrix has so many unique values, I wonder if there is a more automated way of doing this.

4
  • It is a really bad idea to name the output m1, m2, etc. You'll end up having to programatically generate variable names, which is a nightmare. It is better to use a cell array. You'd end up, for example, with m{1}, m{2}, etc. Now writing the above in a loop is easy. But I'm sure you'll get more clever solutions. Commented Jul 17, 2018 at 19:34
  • @Cris Luengo: Thanks for pointing that out. I agree with you and would actually prefer it in a cell array as you described. I've edited my question. Commented Jul 17, 2018 at 19:42
  • What else are you missing here? Do you know how to write a loop in MATLAB? Maybe you are looking for unique to select for which integers to create a logical matrix? Or are you looking for a vectorized approach? (Loops in MATLAB are actually quite fast nowadays). Commented Jul 17, 2018 at 19:47
  • @Cris Luengo, I was trying to avoid looping because my matrices are really large. I tried splitapply in combination with unique but without success so far. Commented Jul 17, 2018 at 19:59

2 Answers 2

3

One option is to create a 3D logical matrix where each 2D plane is one of your desired binary matrices. Assuming you want to test for all integers from 1 to the maximum value found in m, you can do this using either bsxfun or implicit expansion (in versions R2016b or newer of MATLAB):

N = max(m(:));

mm = bsxfun(@eq, m, reshape(1:N, [1 1 N]));
% or
mm = (m == reshape(1:N, [1 1 N]));  % Implicit expansion

And now if you want the binary matrix for m = 2, you simply index into mm:

mat = mm(:, :, 2);
Sign up to request clarification or add additional context in comments.

2 Comments

It works great @gnovice, many thanks! I wasn't aware of implicit expansion in Matlab, so thanks for pointing that out. Just one more thing, is it possible to use implicit expansion when working with multidimensional arrays? I tried m = randi([1 4],4,4,2); m == reshape(repmat(1:N,1,2), [1 1 N 2]); among other things but always got an error: Array dimensions must match for binary array op.
@HappyPy: For your multidimensional case I think the operation you want is mm = (m == reshape(1:N, [1 1 1 N])). Then, mm(:, :, :, 1) will give you a 4-by-4-by-2 logical matrix for the ones in m, mm(:, :, :, 2) will give you a matrix for the twos in mm, etc.
0

If your unique values aren't sequential, you should use unique to get all those values:

[U, ~, upos] = unique(m);
umat = reshape(upos, size(m));
% Note that U(umat) == m.

Now, umat is neat as it has sequential unique integer values and you can work on it instead of original matrix (use gnovice's solution). Or, you can use U instead of this 1:N, again his answer for "matlab-y" approach. Though, I would likely use a loop here. It shouldn't have significant performance difference.

Now, this approach has one problem - it goes through the matrices MANY times. Here, I could imagine a workaround along the lines:

foundInds = m(1);
logMats = cell(1);
logMats{1} = false(size(m));
for i = 1 : numel(m)
    anyFound = false;
    for j = 1 : length(foundInds)
       if (m(i) == foundInds(j))
          anyFound = true;
          logMats{j}(i) = true;
          break;
       end
    end
    if ~anyFound
       % Add the new element.
       foundInds(end+1) = m(i);
       logMats{length(foundInds)} = false(size(m));
       logMats{length(foundInds)}(i) = true;
    end
end

(you need to at least make it less dumb by not changing foundInds and logMats size for every new element by the initial guess of number of unique elements)

However, despite the code goes through the elements only once and does the minimum amount of work needed in theory ... it simply doesn't work well in the current form - it only outperforms gnovice's solution in case you have tons of possible values, yet small matrices (unique works the best here).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.