Calculating mean over column with condition - matlab

So my question is as follows: I have a matrix (let's take
A = [ 1 11 22 33; 44 13 12 33; 1 14 33 44,]
as an example) where I want to calculate the mean for all columns separately. The tricky part is that I only want to calculate the mean for those numbers in each column which are greater than the column 25th percentile.
I was thinking to simply create the 25th percentile and then use this as a criterion for selecting rows. This, unfortunately, does not work.
In order to further clarify: What should happen is to go through each column and calculate the 25th percentile
prctile(A,25,1)
And then calculating the mean only for those numbers which are respectively to their column bigger than the percentile.
Any help?
Thanks!

You can create a version of A which is NaN for values below the 25th percentile, then use the 'omitnan' flag in mean to exclude those points:
A = [1 11 22 33; 44 13 12 33; 1 14 33 44];
B = A; % copy to leave A unaltered
B( B <= prctile(B,25,1) ) = NaN; % Turn values to NaN which we want to exclude
C = mean( B, 1, 'omitnan' ); % Omit the NaN values from the caculation
% C >>
% [ 15.33 13.50 27.50 36.67 ]

Related

Calculate Interval mean of column in matlab (interval not fixed)

I have an array (2000x2) with two variables and want to calculate the mean of column 2 at intervals determined by column 1. How can i do this?
speed=(:,1); %values range from 0-100 cm/s
press=(:,2);
I want to calculate mean pressure at at 5 cm/s intervals of speed. So that I get 20 values for pressure that correspond to 20 intervals of speed.
Should be simple, but I'm still a beginner in Matlab.
The accumarray function does just that:
data = [0 20 33 44 22 56 25 47 81 90; 3 5 4 3 2 4 5 5 6 0].';
speed = data(:,1);
press = data(:,2);
sz = 5; % interval size
fill = NaN; % fill value in the result, for empty groups
group = floor(speed/sz)+1; % compute index of group for each value
result = accumarray(group, press, [], #mean, NaN); % compute mean of each group

Reshape column vector

Hello I'm working with MATLAB and I have a "z" column vector that has dimension of (9680 x 1). I want to reshape it in order to have an array "z" of dimension (44 x 220). I'm doing the following:
z=reshape(z,44,220);
I also tried:
z=reshape(z,[44,220]);
But the output is not right (at least the first row). I can see it by comparing the output matrix with the initial vector.
I just need the 220 first positions of the column vector to be the length of the first row of the matrix, then the next 220 positions of the vector to be the second row of the matrix and so on till obtaining 44 rows.
What am I doing wrong? Thanks for your help.
Matlab stores the matrix values in column major format (this is important during reshape). Since you want row major, you need to do
z = reshape(z, [220 44]).';
i.e. transpose afterwards.
I'd use Andreas H.'s approach.
As an alternative, there's a vec2mat function in the Communications Toolbox that does just that, and even fills missing values if needed:
>> x = 11:18;
>> vec2mat(x,4) %// no padding needed
ans =
11 12 13 14
15 16 17 18
>> vec2mat(x,5) %// padding needed; with 0 by default
ans =
11 12 13 14 15
16 17 18 0 0
>> vec2mat(x,5,-1) %// padding needed; with specified value
ans =
11 12 13 14 15
16 17 18 -1 -1

How can I select random value that previously selected value are excluded from the selection

I want to select a random value but previously selected value are excluded from the selection. How can make like this??
Create a list of random numbers within the range, and pick one at a time
minimum=1;
maximum=16;
randomNumbers=randperm(maximum-minimum+1)+minimum-1
and sample output is randomNumbers=[7 13 2 15 12 4 16 11 9 5 3 1 14 6 8 10]. You can display each number sequentially using, for example,
for k=1:maximum+1-minimum
randomNumbers(k)
end
This approach is generalized one.. A could have any values, some numbers repeating or non repeating.. also any number of(of course upto numel(A)) could be generated.
Code:
A = randi(50,3,3); %// replace this with your own matrix
idx = 1:numel(A); %// generating linear indices
noOfRandNos = 5; %// How many such numbers do you want?
randNos(noOfRandNos,1) = 0; %// pre Allocation
%// This loop is run as many times as the number of such numbers you require.
%// Maximum possible runs will be equal to the numel(A).
for ii = 1:noOfRandNos
randidx = randi(numel(idx)); %// generating a rand Indx within the current size of idx
randNos(ii) = A(idx(randidx)); %// Getting corresponding number in-turn from the indx
idx(randidx) = []; %// removing the particular indx so that it is not repeated
end
Sample Run:
>> A
A =
12 28 25
23 27 32
49 12 34
>> randNos
randNos =
28
49
34
12
32
To pick 5 numbers from the set 1:16 without repetition: use randsample:
result = randsample(1:16, 5);

How can I use values within a MATLAB matrix as indices to determine the location of data in a new matrix?

I have a matrix that looks like the following.
I want to take the column 3 values and put them in another matrix, according to the following rule.
The value in the Column 5 is the row index for the new matrix, and Column 6 is the column index. Therefore 20 (taken from 29,3) should be in Row 1 Column 57 of the new matrix, 30 (from 30,3) should in Row 1 column 4 of the new matrix, and so on.
If the value in column 3 is NaN then I want NaN to be copied over to the new matrix.
Example:
% matrix of values and row/column subscripts
A = [
20 1 57
30 1 4
25 1 16
nan 1 26
nan 1 28
25 1 36
nan 1 53
50 1 56
nan 2 1
nan 2 2
nan 2 3
80 2 5
];
% fill new matrix
B = zeros(5,60);
idx = sub2ind(size(B), A(:,2), A(:,3));
B(idx) = A(:,1);
There are a couple other ways to do this, but I think the above code is easy to understand. It is using linear indexing.
Assuming you don't have duplicate subscripts, you could also use:
B = full(sparse(A(:,2), A(:,3), A(:,1), m, n));
(where m and n are the output matrix size)
Another one:
B = accumarray(A(:,[2 3]), A(:,1), [m,n]);
I am not sure if I understood your question clearly but this might help:
(Assuming your main matrix is A)
nRows = max(A(:,5));
nColumns = max(A(:,6));
FinalMatrix = zeros(nRows,nColumns);
for i=1:size(A,1)
FinalMatrix(A(i,5),A(i,6))=A(i,3);
end
Note that above code sets the rest of the elements equal to zero.

Finding index of vector from its original matrix

I have a matrix of 2d lets assume the values of the matrix
a =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
17 24 1 8 15
11 18 25 2 9
This matrix is going to be divided into three different matrices randomly let say
b =
17 24 1 8 15
23 5 7 14 16
c =
4 6 13 20 22
11 18 25 2 9
d =
10 12 19 21 3
17 24 1 8 15
How can i know the index of the vectors in matrix d for example in the original matrix a,note that the values of the matrix can be duplicated.
for example if i want to know the index of {10 12 19 21 3} in matrix a?
or the index of {17 24 1 8 15} in matrix a,but for this one should return only on index value?
I would appreciate it so much if you can help me with this. Thank you in advance
You can use ismember with the 'rows' option. For example:
tf = ismember(a, c, 'rows')
Should produce:
tf =
0
0
1
0
0
1
To get the indices of the rows, you can apply find on the result of ismember (note that it's redundant if you're planning to use this vector for matrix indexing). Here find(tf) return the vector [3; 6].
If you want to know the number of the row in matrix a that matches a single vector, you either use the method explained and apply find, or use the second output parameter of ismember. For example:
[tf, loc] = ismember(a, [10 12 19 21 3], 'rows')
returns loc = 4 for your example. Note that here a is the second parameter, so that the output variable loc would hold a meaningful result.
Handling floating-point numbers
If your data contains floating point numbers, The ismember approach is going to fail because floating-point comparisons are inaccurate. Here's a shorter variant of Amro's solution:
x = reshape(c', size(c, 2), 1, []);
tf = any(all(abs(bsxfun(#minus, a', x)) < eps), 3)';
Essentially this is a one-liner, but I've split it into two commands for clarity:
x is the target rows to be searched, concatenated along the third dimension.
bsxfun subtracts each row in turn from all rows of a, and the magnitude of the result is compared to some small threshold value (e.g eps). If all elements in a row fall below it, mark this row as "1".
It depends on how you build those divided matrices. For example:
a = magic(5);
d = a([2 1 2 3],:);
then the matching rows are obviously: 2 1 2 3
EDIT:
Let me expand on the idea of using ismember shown by #EitanT to handle floating-point comparisons:
tf = any(cell2mat(arrayfun(#(i) all(abs(bsxfun(#minus, a, d(i,:)))<1e-9,2), ...
1:size(d,1), 'UniformOutput',false)), 2)
not pretty but works :) This would be necessary for comparisons such as: 0.1*3 == 0.3
(basically it compares each row of d against all rows of a using an absolute difference)