MATLAB Answers

mr mo
0

Finding the values right after and right before some values in a matrix

Asked by mr mo
on 6 Nov 2017
Latest activity Commented on by Guillaume
on 8 Nov 2017
Hi. Suppose I have the matrix A of size (m*n).
A = [12 44
93 43
128 44
145 41
180 41
220 40
280 40];
also I have the vector V e.g.
V = [13 20 70 90 95 100 102 110 129 130 145 158 170 185 190 200 207 220 270 280 285 290];
I want to find which one of the rows of matrix A based on its first column values is right after and right before the values of vector V, and if one of the values of the first column of matrix A is equal to the values of vector V, I want to find that row.
For example :
A(2,1) is right before V(5) and V(6) and V(7) and V(8)
A(3,1) is right after V(5) and V(6) and V(7) and V(8)
and in case of equality I want to find this
A(4,1) = V(11)
A(5,1) = V(18)
A(7,1) = V(20)
In other words, I want to find exactly which members of vector V are between which members of first column of matrix A with their indices like this :
V(1) and V(2) and V(3) and V(4) is between A(1,1) and A(2,1)
Thanks for your help.

  2 Comments

what do you mean by "right before"? If I want to explain it myself I would say 93 is right before 94 (and 94 only!). It is not right before 95!
and right after is the immediate next number, not every number after it.
I am looking for this. For example
V(1) and V(2) and V(3) and V(4) is between A(1,1) and A(2,1)

Sign in to comment.

2 Answers

Answer by KL
on 6 Nov 2017
Edited by KL
on 6 Nov 2017

res = find(V>A(1,1) & V<A(2,1))
for all elements,
res = arrayfun(@(x,y) find(V>x & V<y), A(1:end-1,1), A(2:end,1),'uni',0)

  9 Comments

You see, we can make a matrix if the number of elements is same for each row, if you take res, first two rows have 4 elements and then followed by 2 element rows and again 4 element row, finally just one element.
For this reason only we use cell array.
They are very easy to use. You just need to use {} braces. with the current "res", if you type on the command line,
res{1,1}
you will get the indices.
Anyway, if you need the values of A and V, we can create a cell array called out like,
out = arrayfun(@(x,y) [x, y, V(find(V>x & V<y))], A(1:end-1,1), A(2:end,1),'uni',0)
now if you want to access the contents of first row,
>> out{1,1}
ans =
12 93 13 20 70 90
Thanks a lot. You are right about the "we can make a matrix if the number of elements is same for each row". I just forgot that. This is what I need.
Suppose I want to find that only V(10)=130 is lying between which two members of A(:,1). How can I do this process to have the out cell array like your last code?
And in case of equality how can I have the out cell array like the case of inequality? Thanks a lot.

Sign in to comment.


Answer by Guillaume
on 7 Nov 2017

An alternative method that does not involve loops (or arrayfun) but is not necessary faster than KL's:
comp = abs(A(:, 1) - V);
comp(A(:, 1) > V) = inf;
[~, beforeVidx] = min(comp, [], 2);
isequaltoV = A(:, 1) == V(beforeVidx)';
%for display only:
table(A, beforeVidx, isequaltoV)

  4 Comments

Show 1 older comment
You're using an old version of matlab (<R2016b). It's always a good idea to mention such things. In pre-R2016b,
comp = bsxfun(@minus, A(:, 1), V);
Also this error was happened.
comp(A(:, 1) > V) = inf;
Error using >
Matrix dimensions must agree.
Same issue, same solution, use bsxfun:
comp(bsxfun(@gt, A(:, 1), V)) = inf;

Sign in to comment.