4

I'm trying to get a logical matrix as a result of a condition that is specific for each column M(:,i) of the original matrix, based on the value of the same index i in vector N, that is, N(i).

I have looked this up online, but can't find anything quite like it. There must be a simple and clean way of doing this.

M =

     3    -1   100     8
   200     2   300     4
   -10     0     0   400

N =

     4     0    90     7

and my desired solution is, for each column of M(:,i), the values less than N(i):

     1     1     0     0
     0     0     0     1
     1     0     1     0
Dan
  • 45,079
  • 17
  • 88
  • 157
aspasia
  • 179
  • 1
  • 8

2 Answers2

5

It's a standard use-case for bsxfun:

O = bsxfun(@lt, M, N)

Here @lt is calling the "less than" function, i.e. it is the function handle to the < operator. bsxfun will then "expand" N along its singleton dimension by applying the function @lt to each row of M and the whole of N.

Note that you can easily achieve the same thing using a for-loop:

O = zeros(size(M));
for row = 1:size(M,1)
    O(row,:) = M(row,:) < N;
end

Or by using repmat:

O = M < repmat(N, size(M,1), 1);

but in MATLAB the bsxfun is usually the most efficient.

Dan
  • 45,079
  • 17
  • 88
  • 157
  • 1
    `bsxfun` is especially more efficient when working with relational operations - [`BSXFUN on memory efficiency with relational operations`](http://stackoverflow.com/questions/29800560/bsxfun-on-memory-efficiency-with-relational-operations). Just one of the best cases really. – Divakar Nov 11 '15 at 09:03
  • 2
    I learned more than the answer to the question there, thank you! – aspasia Nov 11 '15 at 15:16
3

Possible two-line solution using arrayfun to apply the comparison to each column and index pair:

T = arrayfun(@(jj)M(:,jj) < N(jj), 1:numel(N), 'UniformOutput', false);
result = cat(2,T{:});

Edit: Of course, the bsxfun solution is much more efficient.

mikkola
  • 3,376
  • 1
  • 19
  • 41