Operations within matrix avoiding for loops - matlab

I have a rather simple question but I can't get the proper result in MATLAB.
I am writing a code in Matlab where I have a 200x3 matrix. This data corresponds to the recording of 10 different points, for each of which I took 20 frames.
This is just in order to account for the error in the measuring system. So now I want to calculate the 3D coordinates of each point from this matrix by calculating an average of the measured independent coordinates.
An example (for 1 point with 3 measurements) would be:
MeasuredFrames (Point 1) =
x y z
1.0000 2.0000 3.0000
1.1000 2.2000 2.9000
0.9000 2.0000 3.1000
Point = mean(MeasuredFrames(1:3, :))
Point =
1.0000 2.0667 3.0000
Now I want to get this result but for 10 points, all stored in a [200x3] array, in intervals of 20 frames.
Any ideas?
Thanks in advance!

If you have the Image processing toolbox blockproc could be an option:
A = blockproc(data,[20 3],#(x) mean(x.data,1))
If not the following using permute with reshape works as well:
B = permute(mean(reshape(data,20,10,3),1),[2,3,1])
Explanation:
%// transform data to 3D-Matrix
a = reshape(data,20,10,3);
%// avarage in first dimension
b = mean(a,1);
%// transform back to 10x3 matrix
c = permute(b,[2,3,1])
Some sample data:
x = [ 1.0000 2.0000 3.0000
1.1000 2.2000 2.9000
0.9000 2.0000 3.1000
1.0000 2.0000 3.0000
1.1000 2.2000 2.9000
0.9000 2.0000 3.1000
1.0000 2.0000 3.0000
1.1000 2.2000 2.9000
0.9000 2.0000 3.1000
1.1000 2.2000 2.9000]
data = kron(1:20,x.').';
A = B =
1.5150 3.1200 4.4850
3.5350 7.2800 10.4650
5.5550 11.4400 16.4450
7.5750 15.6000 22.4250
9.5950 19.7600 28.4050
11.6150 23.9200 34.3850
13.6350 28.0800 40.3650
15.6550 32.2400 46.3450
17.6750 36.4000 52.3250
19.6950 40.5600 58.3050

If you do not have access to the blockproc function, you can do it with a combination of reshape:
np = 20 ; %// number of points for averaging
tmp = reshape( A(:) , np,[] ) ; %// unfold A then group by "np"
tmp = mean(tmp); %// calculate mean for each group
B = reshape(tmp, [],3 ) ; %// reshape back to nx3 matrix
In your case, replace A by MeasuredFrames and B by Points, and group in one line:
Points = reshape(mean(reshape( MeasuredFrames (:) , np,[] )), [],3 ) ;

Matrix multiplication can be used:
N=20;
L=size(MeasuredFrames,1);
Points = sparse(ceil((1:L)/N), 1:L, 1)*MeasuredFrames/N;

Related

Getting the Row Matrix

I want to convert a n*n matrix into its respective row matrix in Matlab. How to achieve this ?
For example assume the original matrix is
7.0000 26.0000 6.0000 60.0000 78.5000
1.0000 29.0000 15.0000 52.0000 74.3000
11.0000 56.0000 8.0000 20.0000 104.3000
and I want to get the output as
7.0000 26.0000 6.0000 60.0000 78.5000 1.0000 29.0000 15.0000
52.0000 74.3000 11.0000 56.0000 8.0000 20.0000 104.3000
which is the row matrix.
As you want to reshape it into a vector, reshape might be a bit overkill, as you can just use linear indexing.
A = randi(10,5,5); %Create some matrix
B=A.'; %SLOW
B = B(:).'; %matrix -> vector conversion
On the other hand, the speed of the matrix -> vector conversion does not really matter as it is the initial transpose which is slow, which you'll need for any method, see e.g. Phil's answer.
Easiest solution is:
Anew = reshape(Aold',1,numel(Aold));
Of particular importance is that you need to use the transpose of Aold.
I think what you want is:
reshape(A, 1, []);
where A is your matrix. For example:
A = rand(5,5);
b = reshape(A, 1, []);
will give you a 1x25 matrix.
Suppose your original matrix is A (which has 15 elements)
A = [7.0000 26.0000 6.0000 60.0000 78.5000;
1.0000 29.0000 15.0000 52.0000 74.3000;
11.0000 56.0000 8.0000 20.0000 104.3000]
Now what you need is to reshape A to become a row vector.
reshape(A,1,[]) % Here 1 means you need one row, and [] means you need is as vector
If you want column vector you may use the following
reshape(A,[],1) % this gives a column vector
However, according to your objective the following code will do the job
A = [7.0000 26.0000 6.0000 60.0000 78.5000;
1.0000 29.0000 15.0000 52.0000 74.3000;
11.0000 56.0000 8.0000 20.0000 104.3000];
reshape(A,1,[])
The output will be
ans =
7.0000 1.0000 11.0000 26.0000 29.0000 56.0000 6.0000 15.0000 8.0000 60.0000 52.0000 20.0000 78.5000 74.3000 104.3000
For detailed information, type the following in the command window
help reshape

Matlab - Plot from double data

From an N x 3 matrix with values in third column only having the 4 values 1, 2, 3 & 4, I have to create a bar plot as well as a line plot showing the growth rate for each row (second column values). First row values are called 'Temperature', second 'Growth rate' and third 'Bacteria type'
As of right now my line plot does not work when removing rows with one of the four values in the third column. The matrix could look something like this
39.1220 0.8102 1.0000
13.5340 0.5742 1.0000
56.1370 0.2052 1.0000
50.0190 0.4754 1.0000
24.2970 0.8615 1.0000
37.1830 0.8513 1.0000
59.2390 0.0584 1.0000
45.7840 0.6254 1.0000
51.9480 0.3932 1.0000
42.3400 0.7371 1.0000
25.3870 0.8774 1.0000
57.1870 0.3880 2.0000
37.4580 0.7095 2.0000
46.4190 0.6431 2.0000
38.8380 0.7034 2.0000
11.2930 0.1214 2.0000
32.3270 0.6708 2.0000
42.3150 0.6908 2.0000
36.0600 0.7049 2.0000
28.6160 0.6248 2.0000
56.8570 0.3940 2.0000
51.4770 0.5410 2.0000
52.4540 0.5127 2.0000
28.6270 0.6248 2.0000
39.6590 0.7021 2.0000
53.6280 0.4829 2.0000
56.6750 0.4029 2.0000
43.4230 0.6805 2.0000
20.3390 0.4276 2.0000
42.6930 0.6826 2.0000
13.6030 0.2060 2.0000
30.3360 0.6497 2.0000
43.3470 0.6749 2.0000
56.6860 0.3977 2.0000
50.5480 0.5591 2.0000
34.2270 0.6929 2.0000
47.8370 0.6136 2.0000
30.8520 0.6593 2.0000
51.3290 0.5050 3.0000
29.5010 0.7789 3.0000
34.8950 0.8050 3.0000
44.7400 0.6884 3.0000
51.7180 0.4927 3.0000
40.4810 0.7621 3.0000
38.7370 0.7834 3.0000
26.3020 0.7379 3.0000
32.8210 0.8072 3.0000
45.6900 0.6684 3.0000
54.2200 0.4058 3.0000
46.0430 0.6611 3.0000
10.9310 0.2747 3.0000
43.7390 0.7043 3.0000
31.9250 0.7948 3.0000
31.8910 0.7954 3.0000
15.8520 0.4592 3.0000
50.7340 0.5237 3.0000
26.2430 0.7305 3.0000
22.3110 0.6536 3.0000
14.7690 0.1796 4.0000
17.3260 0.2304 4.0000
41.5570 0.3898 4.0000
52.9660 0.2604 4.0000
58.7110 0.1558 4.0000
And my code is as follows, with data being the matrix (double)
function dataPlot(data)
%1xN matrix with bacteria
A=data(:,3);
%Number of different bacterias is counted, and gathered in a vector
barData = [sum(A(:) == 1), sum(A(:) == 2), sum(A(:) == 3), sum(A(:) == 4)];
figure
bar(barData);
label = {'Salmonella enterica'; 'Bacillus cereus'; 'Listeria'; 'Brochothrix thermosphacta'};
set(gca,'xtick',[1:4],'xticklabel',label)
set(gca,'XTickLabelRotation',45)
ylabel('Observations')
title('Destribution of bacteria')
%The data is divided into four matrices based on the four different bacterias
%Salmonella matrix
S=data;
deleterow = false(size(S, 1), 1);
for n = 1:size(S, 1)
%For column condition
if S(n, 3)~= 1
%Mark line for deletion afterwards
deleterow(n) = true;
end
end
S(deleterow,:) = [];
S=S(:,1:2);
S=sortrows(S,1);
%Bacillus cereus
Ba=data;
deleterow = false(size(Ba, 1), 1);
for p = 1:size(Ba, 1)
%For column condition
if Ba(p, 3)~= 2
%Mark line for deletion afterwards
deleterow(p) = true;
end
end
Ba(deleterow,:) = [];
Ba=Ba(:,1:2);
Ba=sortrows(Ba,1);
%Listeria
L=data;
deleterow = false(size(L, 1), 1);
for v = 1:size(L, 1)
%For column condition
if L(v, 3)~= 3
%Mark line for deletion afterwards
deleterow(v) = true;
end
end
L(deleterow,:) = [];
L=L(:,1:2);
L=sortrows(L,1);
%Brochothrix thermosphacta
Br=data;
deleterow = false(size(Br, 1), 1);
for q = 1:size(Br, 1)
%For column condition
if Br(q, 3)~= 3
%Mark line for deletion afterwards
deleterow(q) = true;
end
end
Br(deleterow,:) = [];
Br=Br(:,1:2);
Br=sortrows(Br,1);
%The data is plotted (growth rate against temperature)
figure
plot(S(:,1), S(:, 2), Ba(:,1), Ba(:, 2), L(:,1), L(:, 2), Br(:,1), Br(:, 2))
xlim([10 60])
ylim([0; Inf])
xlabel('Temperature')
ylabel('Growth rate')
title('Growth rate as a function of temperature')
legend('Salmonella enterica','Bacillus cereus','Listeria','Brochothrix thermosphacta')
Can anyone help me fix it so when I have a matrix without eg 2 in the third column, it will still plot correctly?
I do know how to filter it correctly, and apply that filtering to 'data', so the only problem is the error codes occurring when plotting.
The errors are;
Warning: Ignoring extra legend entries.
> In legend>set_children_and_strings (line 643)
In legend>make_legend (line 328)
In legend (line 254)
In dataPlot (line 82)
In Hovedscript (line 153)
When running this function from a main script with the matrix sorted by growth rate (second column) and filtering for only third row values 1, 3 and 4 to be analyzed. The filtering is done through another function, done in advance, and the new 'data' looks like this.
59.2390 0.0584 1.0000
58.7110 0.1558 4.0000
14.7690 0.1796 4.0000
56.1370 0.2052 1.0000
17.3260 0.2304 4.0000
52.9660 0.2604 4.0000
10.9310 0.2747 3.0000
41.5570 0.3898 4.0000
51.9480 0.3932 1.0000
54.2200 0.4058 3.0000
15.8520 0.4592 3.0000
50.0190 0.4754 1.0000
51.7180 0.4927 3.0000
51.3290 0.5050 3.0000
50.7340 0.5237 3.0000
13.5340 0.5742 1.0000
45.7840 0.6254 1.0000
22.3110 0.6536 3.0000
46.0430 0.6611 3.0000
45.6900 0.6684 3.0000
44.7400 0.6884 3.0000
43.7390 0.7043 3.0000
26.2430 0.7305 3.0000
42.3400 0.7371 1.0000
26.3020 0.7379 3.0000
40.4810 0.7621 3.0000
29.5010 0.7789 3.0000
38.7370 0.7834 3.0000
31.9250 0.7948 3.0000
31.8910 0.7954 3.0000
34.8950 0.8050 3.0000
32.8210 0.8072 3.0000
39.1220 0.8102 1.0000
37.1830 0.8513 1.0000
24.2970 0.8615 1.0000
25.3870 0.8774 1.0000
Again, the bar plot works just fine, but does show all 4 bacteria even when only 3 of them are used, and the problem is in the line plot, with one line not showing in the plot.
Thank you for your time
A solution is to replace the following lines
plot(S(:,1), S(:, 2), Ba(:,1), Ba(:, 2), L(:,1), L(:, 2), Br(:,1), Br(:, 2))
legend('Salmonella enterica','Bacillus cereus','Listeria','Brochothrix thermosphacta')
by
hold on
plot(S(:,1), S(:, 2), 'DisplayName', 'Salmonella enterica');
plot(Ba(:,1), Ba(:, 2), 'DisplayName', 'Bacillus cereus');
plot(L(:,1), L(:, 2), 'DisplayName', 'Listeria');
plot(Br(:,1), Br(:, 2), 'DisplayName', 'Brochothrix thermosphacta');
legend SHOW;
In this way, the legend entries are explitely assigned to a specific plot, which works even if some plots are empty.
Copy and Paste mistake
L == Br in the provided code due to a copy and paste mistake. You should change if Br(q, 3)~= 3 into if Br(q, 3)~= 4.
Result
If I use your second input data (without 2 in the third column), I get the following (without any error message):

Calculating c mature in MATLAB. How can i solve it?

i have a `x=(t*n) stock return matrix, that n is number of stock in a portfolio and t is time. I want calculate
c=M{[x(it)-k(x)][y(it)-k(y)]}
where x(it)
return of stock i in time t
and the median M is taken with respect to the joint CDF of x(t)
and y(t), and k(x) and k(y) are the population medians of x(t) and y(t)
for example:
x=[1 2 3;6 7 5;3 5 6;7 8 9]
x =
1 2 3
6 7 5
3 5 6
7 8 9
t=size(x,1)
n=size(x,2)
medianx=median(x)
medianx =
4.5000 6.0000 5.5000
q=x-medianx(ones(t,1),:)
q =
-3.5000 -4.0000 -2.5000
1.5000 1.0000 -0.5000
-1.5000 -1.0000 0.5000
2.5000 2.0000 3.5000
I can do this to here and I don't know how can i reach c matrix in matlab. I calculate c manually that:
c =
4.2500 3.2500 4.0000
3.2500 2.5000 3.2500
4.0000 3.2500 3.2500
where
c(11)=median of(column1*colum1 of matrix q)=4.25
c(22)=median of(column2*colum2 of matrix q)=2.5
c(33)=median of(column3*colum3 of matrix q)=3.25
c(12) & c(21)=median of(column1*column2 of matrix q)=3.25
c(13) & c(31)=median of(column1*column3 of matrix q)=4
c(23) & c(32)=median of(column2*column3 of matrix q)=3.25
notice that i have a t*n matrix and matrix x just is a example. thanks
You can calculate c from q using this:
c=zeros(3,3); %Pre-allocation
for m=1:3
for n=1:3
c(m,n)= median(q(:,m).*q(:,n));
end
end

Matlab: Index for 5 x 5 grid points

For the following:
x = [0.5 1.5 2.5 3.5 4.5];
for k = 1:1:5
plot(x(k),x','b^','linewidth', 2)
hold on
end
similar to:
[x,y] = meshgrid(0.5:1:4.5);
How can i index each point (blue triangles) coordinates?
Outcome should be like this:
point1 = [x(1),x(1)]; % [0.5,0.5]
point2 = [x(1),x(2)]; % [0.5,1.5]
point3 = [x(1),x(3)]; % [0.5,2.5]
point4 = [x(1),x(4)]; % [0.5,3.5]
point5 = [x(1),x(5)]; % [0.5,4.5]
point6 = [x(2),x(1)]; % [1.5,0.5]
...
point25 = [x(5),x(5)];% [4.5,4.5]
I must do something wrong or matlab program isnt letting me index these today.
[~,idx] = length(point(:));
idxpoint = ind2sub(size(point),idx);
Please write a working example.
Thank you in advance.
You almost had it. You can use meshgrid for that:
x = linspace(0.5, 4.5, 5);
y = linspace(0.5, 4.5, 5);
[Y, X] = meshgrid(x, y);
points = [X(:) Y(:)];
This method has the advantage that you can use different linspace for x and y coordinates.
Now every row of points stores x and y coordinates one point:
points(1,:)
ans =
0.5000
0.5000
points(25,:)
ans =
4.5000
4.5000
You can stack all of your points into an N-by-2 matrix, with each row representing a point"
close all
x = [0.5 1.5 2.5 3.5 4.5];
n = length(x);
X = [];
for k = 1:1:5
plot(x(k),x','b^','linewidth', 2)
X = [X; repmat(x(k),n,1) x'];
hold on
end
% replot on new figure
figure, hold on
plot(X(:,1),X(:,2),'b^','linewidth',2)
% Each row of X is one of your points, i.e.
% Point number 5:
X(5,:)
What about the following?
[x y] = meshgrid(.5:1:4.5);
points = [reshape(x,1,[])',reshape(y,1,[])']
points =
0.5000 0.5000
0.5000 1.5000
0.5000 2.5000
0.5000 3.5000
0.5000 4.5000
1.5000 0.5000
1.5000 1.5000
1.5000 2.5000
1.5000 3.5000
1.5000 4.5000
2.5000 0.5000
2.5000 1.5000
2.5000 2.5000
2.5000 3.5000
2.5000 4.5000
3.5000 0.5000
3.5000 1.5000
3.5000 2.5000
3.5000 3.5000
3.5000 4.5000
4.5000 0.5000
4.5000 1.5000
4.5000 2.5000
4.5000 3.5000
4.5000 4.5000

Indexing during assignment

Say I have this sample data
A =
1.0000 6.0000 180.0000 12.0000
1.0000 5.9200 190.0000 11.0000
1.0000 5.5800 170.0000 12.0000
1.0000 5.9200 165.0000 10.0000
2.0000 5.0000 100.0000 6.0000
2.0000 5.5000 150.0000 8.0000
2.0000 5.4200 130.0000 7.0000
2.0000 5.7500 150.0000 9.0000
I wish to calculate the variance of each column, grouped by class (the first column).
I have this working with the following code, but it uses hard coded indices, requiring knowledge of the number of samples per class and they must be in specific order.
Is there a better way to do this?
variances = zeros(2,4);
variances = [1.0 var(A(1:4,2)), var(A(1:4,3)), var(A(1:4,4));
2.0 var(A(5:8,2)), var(A(5:8,3)), var(A(5:8,4))];
disp(variances);
1.0 3.5033e-02 1.2292e+02 9.1667e-01
2.0 9.7225e-02 5.5833e+02 1.6667e+00
Separate the class labels and the data into different variables.
cls = A(:, 1);
data = A(:, 2:end);
Get the list of class labels
labels = unique(cls);
Compute the variances
variances = zeros(length(labels), 3);
for i = 1:length(labels)
variances(i, :) = var(data(cls == labels(i), :)); % note the use of logical indexing
end
I've done a fair bit of this type of stuff over the years, but to be able to judge, better vs. best, it would help to know what you expect to change in the data set or structure.
Otherwise, if no change is anticipated and the hard code works, stick with it.
Easy, peasy. Use consolidator. It is on the file exchange.
A = [1.0000 6.0000 180.0000 12.0000
1.0000 5.9200 190.0000 11.0000
1.0000 5.5800 170.0000 12.0000
1.0000 5.9200 165.0000 10.0000
2.0000 5.0000 100.0000 6.0000
2.0000 5.5000 150.0000 8.0000
2.0000 5.4200 130.0000 7.0000
2.0000 5.7500 150.0000 9.0000];
[C1,var234] = consolidator(A(:,1),A(:,2:4),#var)
C1 =
1
2
var234 =
0.035033 122.92 0.91667
0.097225 558.33 1.6667
We can test the variances produced, since we know the grouping.
var(A(1:4,2:4))
ans =
0.035033 122.92 0.91667
var(A(5:8,2:4))
ans =
0.097225 558.33 1.6667
It is efficient too.