Reputation: 3743
Say we have two ascending sorted vectors:
V1 V2
12 13
15 16
25 17
29 28
What is the simplest way in Matlab to count how many values of V2
fall between consecutive values of V1
?
In this example the resulting vector should be:
Counts
1
2
1
since
1 - 13(V2) fits between 12-15(V1)
2 - 16 and 17(V2) fits between 15-25(V1)
1 - 28(V2) fits between 25-29(V1)
Upvotes: 1
Views: 66
Reputation: 112689
I can't believe that nobody has thought of histc
yet:
count = histc(v2,v1);
gives, in this case
count =
1 %// 1 value of v2 is >= v1(1) and < v1(2)
2 %// 2 values of v2 are >= v1(2) and < v1(3)
1 %// 1 value of v2 is >= v1(3) and < v1(4)
0 %// 0 values of v2 are == v1(4)
Upvotes: 4
Reputation: 5720
>> v1 = [12 ;15 ;25 ;29];
>> v2 = [13 ;16 ;17 ;28];
>> diff(find(ismember(sort([v1 ;v2]),v1) == 1)) - 1
ans =
1
2
1
magic!! without loops!!
But the logic is quiet easy to understand
Using row vectors instead of column vectors as an example
I first create a sorted list of combination of v1, v2 so
>> v3 = sort([v1 v2])
v3 =
12 13 15 16 17 25 28 29
Then this is the key step, I make members of v1 as 1 in v4 and the rest 0. Like this
>> v4 = ismember(v3,v1)
v4 =
1 0 1 0 0 1 0 1
At this point, the problem is almost solved, I need to find the groups of zeros and thier length
>> diff(find(v4 == 1)) - 1
ans =
1 2 1
No loops, less time to run.
Upvotes: 1
Reputation: 30579
bsxfun
can do all the tests you need, then you can vectorize the combination with &
(element-wise AND), and sum:
>> low = bsxfun(@lt,V1,V2.'); %' each row of V1 < each row of V2
>> high = bsxfun(@gt,V1,V2.'); %' each row of V1 > each row of V2
>> sum(low(1:end-1,:) & high(2:end,:),2)
ans =
1
2
1
NOTE: To check >=
instead of >
, use @ge
(instead of @gt
). Similarly for <=
and <
, use @le
or @lt
.
Upvotes: 1
Reputation: 1500
I think this works without loops:
V1 = [12 15 25 29]';
V2 = [13 16 17 28]';
V3 = [V1 zeros(size(V1)); V2 ones(size(V2))];
V4 = sortrows(V3);
ret = diff(find(V4(:,2)==0))-1
This first creates the Vector
V3 =
12 0
15 0
25 0
29 0
13 1
16 1
17 1
28 1
Then sorts it
V4 =
12 0
13 1
15 0
16 1
17 1
25 0
28 1
29 0
Now the position of the zeros mark the next entry in V1. find
finds those positions and diff substracts the positions, leaving the numbers from V2 between them plus one.
Upvotes: 1
Reputation: 1491
V1 = [12,15,25,29];
V2 = [13,16,17,28];
V3 = zeros(1,length(V1)-1);
count = 0;
for i = 1:length(V1)-1
for k = 1:length(V2)
if(V2(k)>V1(i) && V2(k)<V1(i+1))
count = count+1;
end
end
V3(i) = count;
count = 0;
end
V3
Upvotes: 0