Matlab: Index for 5 x 5 grid points - matlab

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

Related

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):

Operations within matrix avoiding for loops

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;

An array of evenly spaced values when only first and last input is known

I want to create an array of N size, which has inputs evenly spaced apart. For clarification I have the first and last values of an array and want to fill the array N sized with inputs.
I have used linspace
bars = 10;
DeapA = 1;
DeapB = 10;
diameter_pin = (linspace(DeapA, DeapB, bars))
Which gives:
diamter_p =
1 2 3 4 5 6 7 8 9 10
However is there a way of doing this by filling an array as such ?
The reason I want to do this is because in more complicated versions of the above when I used the variable in an equation the values are not being calculated correctly
Not sure exactly what you are trying to do, so here are a few answers
Wrapping numbers around
bars = 10;
DeapA = 1;
DeapB = 10;
diameter_pin = reshape(linspace(DeapA, DeapB, bars*bars), bars, bars)
Gives an array where each column has equally spaced points, and the values keep increasing through the columns
diameter_pin =
1.0000 1.9091 2.8182 3.7273 4.6364 5.5455 6.4545 7.3636 8.2727 9.1818
1.0909 2.0000 2.9091 3.8182 4.7273 5.6364 6.5455 7.4545 8.3636 9.2727
1.1818 2.0909 3.0000 3.9091 4.8182 5.7273 6.6364 7.5455 8.4545 9.3636
1.2727 2.1818 3.0909 4.0000 4.9091 5.8182 6.7273 7.6364 8.5455 9.4545
1.3636 2.2727 3.1818 4.0909 5.0000 5.9091 6.8182 7.7273 8.6364 9.5455
1.4545 2.3636 3.2727 4.1818 5.0909 6.0000 6.9091 7.8182 8.7273 9.6364
1.5455 2.4545 3.3636 4.2727 5.1818 6.0909 7.0000 7.9091 8.8182 9.7273
1.6364 2.5455 3.4545 4.3636 5.2727 6.1818 7.0909 8.0000 8.9091 9.8182
1.7273 2.6364 3.5455 4.4545 5.3636 6.2727 7.1818 8.0909 9.0000 9.9091
1.8182 2.7273 3.6364 4.5455 5.4545 6.3636 7.2727 8.1818 9.0909 10.0000
You can take the transpose of this matrix if you want the rows to be increasing instead.
Repeating Rows/columns
Here, each row is the same
>> nRows = 5;
>> nCols = 10;
>> a = 1;
>> b = 10;
>> diameter_pin = repmat(linspace(a, b, nCols), nRows, 1)
diameter_pin =
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
Here, each column is the same
>> nRows = 5;
>> nCols = 10;
>> a = 1;
>> b = 10;
>> diameter_pin = repmat(linspace(a, b, nRows)', 1, nCols)
diameter_pin =
1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000
3.2500 3.2500 3.2500 3.2500 3.2500 3.2500 3.2500 3.2500 3.2500 3.2500
5.5000 5.5000 5.5000 5.5000 5.5000 5.5000 5.5000 5.5000 5.5000 5.5000
7.7500 7.7500 7.7500 7.7500 7.7500 7.7500 7.7500 7.7500 7.7500 7.7500
10.0000 10.0000 10.0000 10.0000 10.0000 10.0000 10.0000 10.0000 10.0000 10.0000
Equally Spaced points from top-left to bottom-right
In this matrix, each row is equally spaced with the same difference, and each column is equally spaced with the same difference. If the number of rows and columns are the same, then the entire matrix is equally spaced!
First, a rectangular matrix:
>> nRows = 10;
>> nCols = 5;
>> a = 1;
>> b = 10;
>> x = linspace(a, b, nCols);
>> y = linspace(a, b, nRows);
>> [xx, yy] = meshgrid(x, y);
>> zz = mean(cat(3, xx, yy), 3)
zz =
1.0000 2.1250 3.2500 4.3750 5.5000
1.5000 2.6250 3.7500 4.8750 6.0000
2.0000 3.1250 4.2500 5.3750 6.5000
2.5000 3.6250 4.7500 5.8750 7.0000
3.0000 4.1250 5.2500 6.3750 7.5000
3.5000 4.6250 5.7500 6.8750 8.0000
4.0000 5.1250 6.2500 7.3750 8.5000
4.5000 5.6250 6.7500 7.8750 9.0000
5.0000 6.1250 7.2500 8.3750 9.5000
5.5000 6.6250 7.7500 8.8750 10.0000
Now you can see the columns are equally spaced:
>> diff(zz)
ans =
0.5000 0.5000 0.5000 0.5000 0.5000
0.5000 0.5000 0.5000 0.5000 0.5000
0.5000 0.5000 0.5000 0.5000 0.5000
0.5000 0.5000 0.5000 0.5000 0.5000
0.5000 0.5000 0.5000 0.5000 0.5000
0.5000 0.5000 0.5000 0.5000 0.5000
0.5000 0.5000 0.5000 0.5000 0.5000
0.5000 0.5000 0.5000 0.5000 0.5000
0.5000 0.5000 0.5000 0.5000 0.5000
And the rows are equally spaced
>> diff(zz')'
ans =
1.1250 1.1250 1.1250 1.1250
1.1250 1.1250 1.1250 1.1250
1.1250 1.1250 1.1250 1.1250
1.1250 1.1250 1.1250 1.1250
1.1250 1.1250 1.1250 1.1250
1.1250 1.1250 1.1250 1.1250
1.1250 1.1250 1.1250 1.1250
1.1250 1.1250 1.1250 1.1250
1.1250 1.1250 1.1250 1.1250
1.1250 1.1250 1.1250 1.1250
If you want the entire matrix to be equally spaced, then you need the same number of rows and columns. Here is the translation of your code:
>> bars = 10;
>> DeapA = 1;
>> DeapB = 10;
>> x = linspace(DeapA, DeapB, bars);
>> diameter_pin = nan(bars, bars, 2);
>> [diameter_pin(:, :, 1), diameter_pin(:, :, 2)] = meshgrid(x, x);
>> diameter_pin = mean(diameter_pin, 3)
diameter_pin =
1.0000 1.5000 2.0000 2.5000 3.0000 3.5000 4.0000 4.5000 5.0000 5.5000
1.5000 2.0000 2.5000 3.0000 3.5000 4.0000 4.5000 5.0000 5.5000 6.0000
2.0000 2.5000 3.0000 3.5000 4.0000 4.5000 5.0000 5.5000 6.0000 6.5000
2.5000 3.0000 3.5000 4.0000 4.5000 5.0000 5.5000 6.0000 6.5000 7.0000
3.0000 3.5000 4.0000 4.5000 5.0000 5.5000 6.0000 6.5000 7.0000 7.5000
3.5000 4.0000 4.5000 5.0000 5.5000 6.0000 6.5000 7.0000 7.5000 8.0000
4.0000 4.5000 5.0000 5.5000 6.0000 6.5000 7.0000 7.5000 8.0000 8.5000
4.5000 5.0000 5.5000 6.0000 6.5000 7.0000 7.5000 8.0000 8.5000 9.0000
5.0000 5.5000 6.0000 6.5000 7.0000 7.5000 8.0000 8.5000 9.0000 9.5000
5.5000 6.0000 6.5000 7.0000 7.5000 8.0000 8.5000 9.0000 9.5000 10.0000
This matrix is equally spaced along each dimension.
Well that's all I could think of. I encourage you to check out the MATLAB help documentation for all the functions I called.
If you want to avoid using linspace (though I don't see why), you could use:
diameter_pin = DeapA : (DeapB-DeapA)/(bars-1) : DeapB;

implementing "not equal to " loop in matlab

i have a simple problem i am quite new to matlab so i am having problem in implementing it i have two 64x2 matrices u and h.i have to check if a single row in u is not equal to all of the rows in h.then the row which is not equal should be saved in a separate matrix meanwhile i have written this code but what it does is that r(i,:) get all the values of u(i,:) when this code runs, what i want is that only those values of u(i,:) should be stored in r which are not similar to any row in h matrix.
h=[];
for j=1:8
for i=1:8
h=[h; i j];
end
end
u=[5.3,1.4;6,8;2,3;3,5.5;2.6,8;3.7,2;4,2;5,3;1.9,8;5.4,4;3.2,3;2,2;2,4;2,3;8,2.2;8,4;7.3,1.5;6.2,5.1;2.4,1.5;3,5;2,7.1;1.8,2.7;3,4;6,5;6,1;5,4;4,6;3.5,2;5,7;7.2,8;7,7;5,5;6,3;6,6;1,2;5,8;3,5;1,5;2,2;2,1;6,3;4,7;6,8;3,6;1,6;5,2;3,5;8,7;8,4;4,8;1,1;6,3;7,5;8,1;1,6;4,5;5,5;6,7;6,7;6,7;6,3;3,4;5,7;1,1]
for i=1
for j=1:64
if u(i,:)==h(j,:)
c=1
else
c=0
if c==0
r(i,:)=u(i,:)
end
end
end
end
can anyone help me please
You can do it in one line with ismember:
r = u(~ismember(u,h,'rows'),:);
With your example data, the result is
>> r
r =
5.3000 1.4000
3.0000 5.5000
2.6000 8.0000
3.7000 2.0000
1.9000 8.0000
5.4000 4.0000
3.2000 3.0000
8.0000 2.2000
7.3000 1.5000
6.2000 5.1000
2.4000 1.5000
2.0000 7.1000
1.8000 2.7000
3.5000 2.0000
7.2000 8.0000
use setdiff with 'rows' option to compute r. Please avoid unnecessary loops. pre-allocate when possible.
% construct h without loop
[h{1} h{2}]=ndgrid(1:8,1:8);
h=[h{1}(:) h{2}(:)];
% get r using setdiff
r = setdiff( u, h, 'rows')
Results with
r =
1.8000 2.7000
1.9000 8.0000
2.0000 7.1000
2.4000 1.5000
2.6000 8.0000
3.0000 5.5000
3.2000 3.0000
3.5000 2.0000
3.7000 2.0000
5.3000 1.4000
5.4000 4.0000
6.2000 5.1000
7.2000 8.0000
7.3000 1.5000
8.0000 2.2000
Solution of you question in NlogN complexity (N=64):
N=size(h,1);
[husorted,origin_husorted,destination_hu]=unique([h;u],'rows','first');
iduplicates=destination_hu(N+1:end)<=destination_hu(N),:);
r=u;
r(iduplicates,:)=0;
destination_uh is the only output of unique that is useful; It verifies [h;u]=husorted(destination_uh,:)]. 'first' ensures that if line i of u is equal line j of h, then destination_uh(i+N) is equal to destination_uh(j).
Solution for your particular h, with complexity N:
r=u;
r(all(u==round(u)&u>=1&u<=8,2),:)=0;

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.