count elements falling within certain thresholds i

2020-05-06 08:50发布

问题:

I have a huge vector. I have to count values falling within certain ranges. the ranges are like 0-10, 10-20 etc. I have to count the number of values which fall in certain range.

I did something like this :

for i=1:numel(m1)
if (0<m1(i)<=10)==1
k=k+1;
end
end

Also:

if not(isnan(m1))==1
x=(0<m1<=10);
end

But both the times it gives array which contains all 1s. What wrong am I doing?

回答1:

You can do something like this (also works for non integers)

k = sum(m1>0 & m1<=10)


回答2:

You can use logical indexing. Observe:

>> x = randi(40, 1, 10) - 20
x =
  -2    17   -12    -9   -14   -14    15     4     2   -14
>> x2 = x(0 < x & x < 10)
x2 =
   4     2
>> length(x2)
ans =
    2

and the same done in one step:

>> length(x(0 < x & x < 10))
ans =
    2


回答3:

to count the values in a specific range you can use ismember,

if m1 is vector use,

k = sum(ismember(m1,0:10));

If m1 is matrix use k = sum(sum(ismember(m1,0:10)));

for example,

m1=randi(20,[5 5])

 9    10     6    10    16
 8     9    14    20     6
16    13    14     7    11
16    15     4    12    14
 4    16     3     5    18

sum(sum(ismember(m1,1:10)))

12


回答4:

Why not simply do something like this?

% Random data
m1 = 100*rand(1000,1);

%Count elements between 10 and 20
m2 = m1(m1>10 & m1<=20);
length(m2) %number of elements of m1 between 10 and 20

You can then put things in a loop

% Random data
m1 = 100*rand(1000,1);

nb_elements = zeros(10,1);

for k=1:length(nb_elements)
    temp = m1(m1>(10*k-10) & m1<=(10*k));
    nb_elements(k) = length(temp);
end 

Then nb_elements contains your data with nb_elements(1) for the 0-10 range, nb_elements(2) for the 10-20 range, etc...



回答5:

Matlab does not know how to evaluate the combined logical expression

(0<m1(i)<=10)

Insted you should use:

for i=1:numel(m1)
    if (0<m1(i)) && (m1(i)<=10)
        k=k+1;
    end
end

And to fasten it up probably something like this:

sum((0<m1) .* (m1<=10))


回答6:

Or you can create logical arrays and then use element-wise multiplication. Don't know how fast this is though and it might use a lot of memory for large arrays.

Something like this

A(find((A>0.2 .* (A<0.8)) ==1))

Generate values

A= rand(5)

A =

0.414906   0.350930   0.057642   0.650775   0.525488
0.573207   0.763477   0.120935   0.041357   0.900946
0.333857   0.241653   0.421551   0.737704   0.162307
0.517501   0.491623   0.016663   0.016396   0.254099
0.158867   0.098630   0.198298   0.223716   0.136054

Find the intersection where the values > 0.8 and < 0.2. This will give you two logical arrays and the values where A>0.2 and A<0.8 will be =1 after element-wise multiplication.

find((A>0.2 .* (A<0.8)) ==1)

Then apply those indices to A

A(find((A>0.2 .* (A<0.8)) ==1))

ans =

   0.41491
   0.57321
   0.33386
   0.51750
   0.35093
   0.76348
   0.24165
   0.49162
   0.42155
   0.65077
   0.73770
   0.22372
   0.52549
   0.90095
   0.25410