Adding data in intervals in Matlab - matlab

Hi I have data in MATLAB like this:
F =
1.0000 1.0000
2.0000 1.0000
3.0000 1.0000
3.1416 9.0000
4.0000 1.0000
5.0000 1.0000
6.0000 1.0000
6.2832 9.0000
7.0000 1.0000
8.0000 1.0000
9.0000 1.0000
9.4248 9.0000
10.0000 1.0000
I am looking for a way to sum the data in specific intervals. Example if I want my sampling interval to be 1, then the end result should be:
F =
1.0000 1.0000
2.0000 1.0000
3.0000 10.0000
4.0000 1.0000
5.0000 1.0000
6.0000 10.0000
7.0000 1.0000
8.0000 1.0000
9.0000 10.0000
10.0000 1.0000
i.e data is accumulated in the second column based on sampling the first row. Is there a function in MATLAB to do this?

Yes by combining histc() and accumarray():
F =[1.0000 1.0000;...
2.0000 1.0000;...
3.0000 1.0000;...
3.1416 9.0000;...
4.0000 1.0000;...
5.0000 1.0000;...
6.0000 1.0000;...
6.2832 9.0000;...
7.0000 1.0000;...
8.0000 1.0000;...
9.0000 1.0000;...
9.4248 9.0000;...
10.0000 1.0000];
range=1:0.5:10;
[~,bin]=histc(F(:,1),range);
result= [range.' accumarray(bin,F(:,2),[])]
If you run the code keep in mind that I changed the sampling interval (range) to 0.5.
This code works for all sampling intervals just define your wanted interval as range.

Yes and that's a job for accumarray:
Use the values in column 1 of F to sum (default behavior of accumarray) the elements in the 2nd column.
For a given interval of size s (Thanks to Luis Mendo for that):
S = accumarray(round(F(:,1)/s),F(:,2),[]); %// or you can use "floor" instead of "round".
S =
1
1
10
1
1
10
1
1
10
1
So constructing the output by concatenation:
NewF = [unique(round(F(:,1)/s)) S]
NewF =
1 1
2 1
3 10
4 1
5 1
6 10
7 1
8 1
9 10
10 1
Yay!!

Related

Matlab: Inserting copies of the previous rows, them applying a pattern to 2 columns

Another question from the thick guy (me)... apologies - help much appreciated!
Here is an example sample from a larger matrix
0 1.0000 1.0000 60.0000 100.0000 0 0.2500
0 1.0000 1.0000 62.0000 100.0000 0.2500 0.2500
0 1.0000 1.0000 63.0000 100.0000 0.5000 0.2500
1.0000 1.0000 1.0000 58.0000 100.0000 0.7500 0.2500
1.0000 1.0000 1.0000 59.0000 100.0000 1.0000 0.2500
1.0000 1.0000 1.0000 65.0000 100.0000 1.2500 0.2500
2.0000 1.0000 1.0000 55.0000 100.0000 1.5000 0.2500
2.0000 1.0000 1.0000 57.0000 100.0000 1.7500 0.2500
2.0000 1.0000 1.0000 60.0000 100.0000 2.0000 0.2500
3.0000 1.0000 1.0000 54.0000 100.0000 2.2500 0.2500
3.0000 1.0000 1.0000 55.0000 100.0000 2.5000 0.2500
3.0000 1.0000 1.0000 59.0000 100.0000 2.7500 0.2500
4.0000 1.0000 1.0000 55.0000 100.0000 3.0000 0.2500
4.0000 1.0000 1.0000 56.0000 100.0000 3.2500 0.2500
4.0000 1.0000 1.0000 60.0000 100.0000 3.5000 0.2500
5.0000 1.0000 1.0000 53.0000 100.0000 3.7500 0.2500
5.0000 1.0000 1.0000 54.0000 100.0000 4.0000 0.2500
5.0000 1.0000 1.0000 59.0000 100.0000 4.2500 0.2500
6.0000 1.0000 1.0000 53.0000 100.0000 4.5000 0.2500
6.0000 1.0000 1.0000 56.0000 100.0000 4.7500 0.2500
6.0000 1.0000 1.0000 58.0000 100.0000 5.0000 0.2500
7.0000 1.0000 1.0000 58.0000 100.0000 5.2500 0.2500
7.0000 1.0000 1.0000 60.0000 100.0000 5.5000 0.2500
7.0000 1.0000 1.0000 65.0000 100.0000 5.7500 0.2500
8.0000 1.0000 1.0000 53.0000 100.0000 6.0000 0.2500
8.0000 1.0000 1.0000 54.0000 100.0000 6.2500 0.2500
8.0000 1.0000 1.0000 63.0000 100.0000 6.5000 0.2500
9.0000 1.0000 1.0000 61.0000 100.0000 6.7500 0.2500
9.0000 1.0000 1.0000 62.0000 100.0000 7.0000 0.2500
9.0000 1.0000 1.0000 65.0000 100.0000 7.2500 0.2500
etc....
For every z (the value of z has been prescribed earlier in the code) rows I'd like 3 copies of the rows to be inserted verbatim beneath them as follows (in this example z = 3) :
0 1.0000 1.0000 60.0000 100.0000 0 0.2500
0 1.0000 1.0000 62.0000 100.0000 0.2500 0.2500
0 1.0000 1.0000 63.0000 100.0000 0.5000 0.2500
0 1.0000 1.0000 60.0000 100.0000 0 0.2500
0 1.0000 1.0000 62.0000 100.0000 0.2500 0.2500
0 1.0000 1.0000 63.0000 100.0000 0.5000 0.2500
0 1.0000 1.0000 60.0000 100.0000 0 0.2500
0 1.0000 1.0000 62.0000 100.0000 0.2500 0.2500
0 1.0000 1.0000 63.0000 100.0000 0.5000 0.2500
0 1.0000 1.0000 60.0000 100.0000 0 0.2500
0 1.0000 1.0000 62.0000 100.0000 0.2500 0.2500
0 1.0000 1.0000 63.0000 100.0000 0.5000 0.2500
1.0000 1.0000 1.0000 58.0000 100.0000 0.7500 0.2500
1.0000 1.0000 1.0000 59.0000 100.0000 1.0000 0.2500
1.0000 1.0000 1.0000 65.0000 100.0000 1.2500 0.2500
1.0000 1.0000 1.0000 58.0000 100.0000 0.7500 0.2500
1.0000 1.0000 1.0000 59.0000 100.0000 1.0000 0.2500
1.0000 1.0000 1.0000 65.0000 100.0000 1.2500 0.2500
1.0000 1.0000 1.0000 58.0000 100.0000 0.7500 0.2500
1.0000 1.0000 1.0000 59.0000 100.0000 1.0000 0.2500
1.0000 1.0000 1.0000 65.0000 100.0000 1.2500 0.2500
1.0000 1.0000 1.0000 58.0000 100.0000 0.7500 0.2500
1.0000 1.0000 1.0000 59.0000 100.0000 1.0000 0.2500
1.0000 1.0000 1.0000 65.0000 100.0000 1.2500 0.2500
etc
Next I'd like column 1 to be replaced and to now have the pattern
[0 0 0 5 5 5 10 11 12 17 17 17 ]
which would then repeat (always from 5 integers later, until the end of the pattern so that the next 12 entries would be:
[22 22 22 27 27 27 32 33 34 39 39 39]
and so on.
It would be great if the code were relatively idiot-friendly (me-friendly) so
that I can easily manipulate this repeating pattern if need be. For example if z
were 4 rather than 3 then I would want the pattern
[0 0 0 0 5 5 5 5 10 11 12 13 18 18 18 18]
...Column 6 should then be replaced with a column that relates to column
1 in a (column_1 * 0.25) relationship.
i.e. for the above sample, where column 1 is:
[0 0 0 5 5 5 10 11 12 17 17 17 22 22 22 27 27 27 32 33 34 39 39 39]
column 6 would be:
[0 0 0 1.2500 1.2500 1.2500 2.5000 2.7500 3.0000 4.2500 4.2500 4.2500 5.5000
5.5000 5.5000 6.7500 6.7500 6.7500 8.0000 8.2500 8.5000 9.7500 9.7500
9.7500]
Can you help with that at all? Thanks very much in advance
TL;DR : For the final code : Go to section Full Code
The first part at least looks like a good job for reshape and repmat.
The tricky part is to not mess up with the dimensions.
Another approach will be to use cells and the function cellfun.
In this answer i will use a toy example defined as follow :
[~,ArrayIn]=meshgrid(1:7,1:20);
ArrayIn =
1 1 1 1 1 1 1
2 2 2 2 2 2 2
3 3 3 3 3 3 3
.....
z=3;
1. FIRST APPROACH : Use repmat and reshape :
Now, basically, the code will operate 3 major steps :
Step 1 : reshape the matrix so that it becomes a matrix of size size(ArrayIn,2)xzxsize(ArrayIn,1)/z
reshapedArrayIn=reshape(ArrayIn.',size(ArrayIn,2),z,[]);
Note that, after this step, the slices along the 3rd dimension are exactly the slices of length z that you want to repeat 3 times (only they are transposed, but it's needed because of the way reshape works).
reshapedArrayIn =
ans(:,:,1) =
1 2 3
1 2 3
1 2 3
1 2 3
1 2 3
1 2 3
1 2 3
ans(:,:,2) =
4 5 6
4 5 6
4 5 6
4 5 6
4 5 6
4 5 6
4 5 6
...
Also note that if the number of rows in your matrix is not dividable by z in the first place, the code will fail and you'll have to add extra lines before the call to reshape in order for it to work :
% Optional
if mod(size(ArrayIn,1),z)~=0
ArrayIn=[ArrayIn;zeros(z-mod(size(ArrayIn,1),z),size(ArrayIn,2))];
end
Step 2 : repeat the matrix 3 times along the second dimension
repArray=repmat(reshapedArrayIn,1,3,1);
Step 3 : reshape your matrix again in order to get a 2 dimensional matrix back, transpose the result to get it right
ArrayOut=reshape(repArray,size(ArrayIn,2),size(ArrayIn,1)*3).';
The result is as intended :
ArrayOut =
1 1 1 1 1 1 1
2 2 2 2 2 2 2
3 3 3 3 3 3 3
1 1 1 1 1 1 1
2 2 2 2 2 2 2
3 3 3 3 3 3 3
...
2. SECOND APPROACH : use cellfun
Another possibility to achieve this would be to convert you matrix to a cell and then use the function cellfun on all your subcells (This code would go after ArrayIn has been padded so that its number of rows is dividable by z:
Idy=7;
Idx=z*ones(size(ArrayIn,1)/z,1);
ArrayCell=mat2cell(ArrayIn,Idx,Idy);
CellOut=cellfun(#(A) repmat(A,3,1),ArrayCell,'UniformOutput',false);
ArrayOut=cell2mat(CellOut);
Giving also the expected result :
ArrayOut =
1 1 1 1 1 1 1
2 2 2 2 2 2 2
3 3 3 3 3 3 3
1 1 1 1 1 1 1
2 2 2 2 2 2 2
3 3 3 3 3 3 3
...
PART 2
For this part you can use what #tim gave you in the comments, although with a slight modification to take the length of your columns into account :
A = [zeros(1,z) 5*ones(1,z) 10:(9+z) 17*ones(1,z)];
m=ceil(size(ArrayOut,1)/(4*z));
UncutCol=repmat(A.',1,m)+repmat(22(*0:(m-1)),length(A),1);
Column1Out=UncutCol(1:size(ArrayOut,1));
Column6Out=Column1Out*0.25;
ArrayOut(:,1)=Column1Out;
ArrayOut(:,6)=Column6Out;
FULL CODE :
Approach 1 :
z=3;
[~,ArrayIn]=meshgrid(1:7,1:20);
if mod(size(ArrayIn,1),z)~=0
ArrayIn=[ArrayIn;zeros(z-mod(size(ArrayIn,1),z),size(ArrayIn,2))];
end
reshapedArrayIn=reshape(ArrayIn.',size(ArrayIn,2),z,[]);
repArray=repmat(reshapedArrayIn,1,3,1);
ArrayOut=reshape(repArray,size(ArrayIn,2),size(ArrayIn,1)*3).';
A = [zeros(1,z) 5*ones(1,z) 10:(9+z) 17*ones(1,z)];
m=ceil(size(ArrayOut,1)/(4*z));
UncutCol=repmat(A.',1,m)+repmat(22*(0:(m-1)),length(A),1);
Column1Out=UncutCol(1:size(ArrayOut,1));
Column6Out=Column1Out*0.25;
ArrayOut(:,1)=Column1Out;
ArrayOut(:,6)=Column6Out;
Approach 2 :
z=3;
[~,ArrayIn]=meshgrid(1:7,1:20);
if mod(size(ArrayIn,1),z)~=0
ArrayIn=[ArrayIn;zeros(z-mod(size(ArrayIn,1),z),size(ArrayIn,2))];
end
Idy=7;
Idx=z*ones(size(ArrayIn,1)/z,1);
ArrayCell=mat2cell(ArrayIn,Idx,Idy);
CellOut=cellfun(#(A) repmat(A,3,1),ArrayCell,'UniformOutput',false);
ArrayOut=cell2mat(CellOut);
A = [zeros(1,z) 5*ones(1,z) 10:(9+z) 17*ones(1,z)];
m=ceil(size(ArrayOut,1)/(4*z));
UncutCol=repmat(A.',1,m)+repmat(22*(0:(m-1)),length(A),1);
Column1Out=UncutCol(1:size(ArrayOut,1));
Column6Out=Column1Out*0.25;
ArrayOut(:,1)=Column1Out;
ArrayOut(:,6)=Column6Out;
Final Result :
ArrayOut =
0 1.0000 1.0000 1.0000 1.0000 0 1.0000
0 2.0000 2.0000 2.0000 2.0000 0 2.0000
0 3.0000 3.0000 3.0000 3.0000 0 3.0000
5.0000 1.0000 1.0000 1.0000 1.0000 1.2500 1.0000
5.0000 2.0000 2.0000 2.0000 2.0000 1.2500 2.0000
5.0000 3.0000 3.0000 3.0000 3.0000 1.2500 3.0000
10.0000 1.0000 1.0000 1.0000 1.0000 2.5000 1.0000
11.0000 2.0000 2.0000 2.0000 2.0000 2.7500 2.0000
12.0000 3.0000 3.0000 3.0000 3.0000 3.0000 3.0000
17.0000 4.0000 4.0000 4.0000 4.0000 4.2500 4.0000
17.0000 5.0000 5.0000 5.0000 5.0000 4.2500 5.0000
17.0000 6.0000 6.0000 6.0000 6.0000 4.2500 6.0000
22.0000 4.0000 4.0000 4.0000 4.0000 5.5000 4.0000
22.0000 5.0000 5.0000 5.0000 5.0000 5.5000 5.0000
22.0000 6.0000 6.0000 6.0000 6.0000 5.5000 6.0000
.....
I also want to provide a second solution, everything you need to know is provided as comments:
%%% INPUT DATA %%%
N = 3;
[~, A]=meshgrid(1:7,1:21);
numRows = size(A, 1);
if(mod(numRows, N) ~= 0)
% do padding here so that numRows can be devided by N, you can do it yourself :-)
end
%%% FIRST PART %%%
cnt = reshape(1:numRows,[N, numRows/N]) % create matrix which contains indices 1:numRows (number of Rows of A) in the desired manner
idx = repmat(cnt, N+1, 1) % number of copies of every line you want: N (so you'd have N+1 entries of every row (1 base and N copies))
A_cop = A(idx(:), :) % now idx(:) will give you the row-indices to replicate the rows of A in the desired manner
% --> 3-liner :-) could even be summed up in one single codeline :D
%%% SECOND PART %%%
c = [zeros(1,N) 5*ones(1,N) 10:(9+N) 17*ones(1,N)]; % base format
c2 = repmat(c', 1, ceil(size(A_cop, 1)/length(c))); % replicate it so that +i*22 can be added easily column-wise (i=column index)
c3 = bsxfun(#plus, c2, [(0:(size(c2,2)-1))]*22);
firstCol = c3(:); % linearize column-major memory
%%% THIRD PART -> merge both parts %%%
A_cop(:, 1) = firstCol(1:size(A_cop,1)); % set first column
A_cop(:, 6) = A_cop(:, 1)*0.25;
I think my first part might be a bit easier to understand then the solution from Bill, isnt it?
Im using indexing to copy rows within the input matrix A. That means, I generate a vector which contains the row-indices which I want to take from A, and this vector can contain values multiple times.
My example index-vector looks like this:
>> idx(:)
ans =
1
2
3
1
2
3
1
2
3
1
2
3
4
5
6
4
5
6
4
5
6
4
5
6
7
8
9
...
Using this, I make the final matrix A_cop and afterwards I apply the second part as described above in the comment --> replicate the base format c in a matrix and sum +i*22 in the i-th column, then linearizing the memory to yield one row-vector :-)

Isolines/contour in matlab

I want to make a contour plot of three variables.
x coordinate , y coordinate and speed
Then I wish to depict the velocity directions on same plot with quiver.
Code:
k=49;
data_k=data(:,1)==k&sp>sp_ths;%filter data
x=xcor(data_k);y=ycor(data_k);sp_k=sp(data_k);vx_k=vx(data_k);vy_k=vy(data_k);
if contour_plot
[Xq, Yq] = meshgrid(x,y);
Zq =griddata(x,y,sp_k,Xq,Yq);
contour(Xq,Yq,Zq,5)%,'ShowText','on');
end
hold on
quiver(x, y, vx_k*5, vy_k*5, 0, 'k');
Output:
contour seems incorrect, I cant understand why though.
Data:
>> [x,y,vx_k,vy_k,sp_k]
ans =
57.3030 61.6410 0.8965 0.4430 2.0000
84.9540 -0.0559 0.9534 0.3017 2.0000
80.3200 7.7009 0.9009 0.4339 2.0000
76.6780 -35.6720 0.9391 -0.3437 2.0000
61.4120 54.7280 0.3449 0.9386 2.0000
70.9940 32.3250 0.7934 0.6088 2.0000
-77.8030 4.8428 -0.9998 -0.0178 2.0000
-39.4330 66.0040 -0.6452 0.7640 2.0000
-41.1680 -70.1010 -0.9055 -0.4244 2.0000
57.7840 -58.3810 0.9264 -0.3765 2.0000
-70.2350 -8.8322 -0.9975 0.0712 2.0000
-77.6940 -26.3810 -0.9676 -0.2525 2.0000
-49.7200 -48.1560 -0.5801 -0.8145 2.0000
-34.4620 -76.7420 -0.6990 -0.7151 2.0000
68.3490 21.6690 0.9678 -0.2516 2.0000
71.7360 -16.5990 0.9287 -0.3709 2.0000
17.9180 -66.0220 0.5107 -0.8598 2.0000
-57.2370 -55.8160 -0.9522 -0.3055 2.0000
86.0120 5.7037 0.9336 0.3583 2.0000
75.7290 16.6260 0.9946 0.1035 1.9114
-78.2140 4.6192 -0.9969 0.0783 2.0000
42.9320 -63.1170 0.5138 -0.8579 2.0000
-56.5820 39.2650 -0.2098 0.9777 2.0000
-18.2490 75.0340 -0.0854 0.9963 2.0000
75.4960 -28.2940 0.8437 -0.5367 2.0000
-17.6210 74.9380 -0.0340 0.9994 2.0000
-10.9350 -79.1950 -0.3356 -0.9420 2.0000
-16.2720 69.7160 0.2938 0.9559 2.0000
-70.9780 -37.1290 -0.9887 0.1496 2.0000
71.9370 -38.4470 0.8501 -0.5266 2.0000
73.3310 -7.0563 0.9994 0.0341 2.0000
83.7780 19.1370 0.8500 0.5268 2.0000
-8.1897 79.2620 0.0479 0.9989 2.0000
56.7250 62.4670 0.9049 0.4256 2.0000
56.6710 62.1070 0.8763 0.4818 2.0000
77.0110 9.7810 0.9787 -0.2053 2.0000
56.3630 62.7070 0.9476 0.3195 2.0000
84.0260 0.2988 0.9618 0.2737 2.0000
-68.5600 -42.1320 -0.9822 -0.1880 2.0000
55.5620 63.5370 0.6724 0.7402 2.0000
19.3120 -67.2460 0.1840 -0.9829 2.0000
-71.6530 28.4280 -0.9346 0.3558 2.0000
-35.6610 -75.9520 -0.1767 -0.9843 2.0000
33.1410 -75.3810 -0.1116 -0.9938 2.0000
55.1580 56.8510 0.5865 0.8099 2.0000
34.6410 -75.9710 0.3960 -0.9183 2.0000
57.9810 -58.1830 0.8255 -0.5645 2.0000
62.0610 -56.7770 0.8238 -0.5669 2.0000
46.5930 -68.1200 0.9947 -0.1029 2.0000
38.4250 -74.4980 0.3652 -0.9309 2.0000
-46.0560 -67.3300 -0.3544 -0.9351 2.0000
75.8290 18.4470 0.9997 0.0244 1.9114
72.4200 31.8080 0.9841 0.1777 2.0000
61.8330 -53.1870 0.9163 -0.4005 2.0000
-62.1240 -25.1080 -0.6117 -0.7911 2.0000
57.0410 62.0730 0.8391 0.5440 2.0000
73.0400 -2.7887 0.9313 0.3643 2.0000
39.0000 -73.7550 0.3970 -0.9178 2.0000
81.8430 -20.8660 0.9697 -0.2443 2.0000
-77.8410 4.7747 -0.9584 0.2853 2.0000
I hope I have the answer for you here: Drawing 3D contour from 3D data
For start, contour and contour3 plots are to represent scalar fields, not vector fields. For vector field You can use quiver and quiver3 plots.
Note that for Contours You need two M-vectors of x and y coordinates and one M-matrix of z data, where z(ii,jj) corresponds to x(ii) and y(jj), but for quiver you need M-vectors of coordinates and M-vectors of vector directions, where x(ii), y(ii), z(ii), u(ii), v(ii) and w(ii) represent one "arrow" in the plot.
It would me helpful to provide image how it should look like.

Efficiently finding a value from one vector in another matlab: error checking if empty

I have 3 vectors: npdf, tn(:,1) and tn(:,2) and am finding the values of npdf in tn(:,2) line by line:
[npdf(1:20,1), tn(1:20,:)]
ans =
8.0000 3.0000 1.0000
11.0000 2.9167 1.0000
1.0000 3.3000 1.0000
11.0000 1.2167 1.0000
5.0000 2.8167 1.0000
1.0000 2.4000 1.0000
2.0000 2.4500 1.0000
4.0000 0.2500 1.0000
15.0000 3.7500 1.0000
15.0000 4.9167 1.0000
1.0000 2.8167 2.0000
17.0000 0.2500 2.0000
15.0000 1.0000 3.0000
4.0000 3.0000 3.0000
8.0000 0.5833 3.0000
1.0000 0.5833 3.0000
3.0000 5.0000 5.0000
11.0000 3.7500 6.0000
8.0000 3.0000 7.0000
15.0000 2.8000 7.0000
for i=1:length(npdf)
[LOCA,~]=ismember(tn(:,2),npdf(i,1,1));
dummy=find(LOCA~=0);
tpdf(i,1)=tn(randi(length(dummy),1,1),1);
end
each time it finds the value of npdf in tn(:,2) it chooses a value from tn(:,1).
Here's the problem: if it can't locate the value from npdf in tn(:,2) then I need to choose the nearest value (in magnitude) in tn(:,2) and proceed. Either that or some sort of interpolation between nearest values.. How would you do this most efficiently?
At your discretion to change the code, it doesn't look very efficient to me.
It can be done easily by using knnsearch as follows:
[idx,D]=knnsearch(tn(:,2),npdf,'K',size(tn,1));
for i=1:size(D,1)
tpdf(i,1)=tn(randi(sum(D(i,:)==min(D(i,:))),1,1),1);
end
It finds distance of each value in npdf to all the values in tn. Then it considers only the nearest value. Then it selects a random indices from tn(:,1) as per your code.

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.

Is there a way to do partial average over matrix in matlab

I have a matrix (table actually) which I imported from a file:
1.0000 1.9736
4.0000 0.2016
9.0000 0.0584
10.0000 0.0495
5.0000 0.1845
2.0000 0.6873
1.0000 1.4177
2.0000 0.4699
5.0000 0.1555
10.0000 0.0435
13.0000 0.0326
8.0000 0.0860
5.0000 0.1685
4.0000 0.1956
5.0000 0.1433
8.0000 0.0675
13.0000 0.0335
13.0000 0.0327
10.0000 0.0431
9.0000 0.0582
10.0000 0.0551
13.0000 0.0308
I want to get the average of each of the occurance on left column. That is:
avg = [
1.0000 1.69565
2.0000 0.5786
4.0000 0.1978]
and so on. I could do this with a wile or for group but this is not the matlab way. So how can I do this?
a=[randi(5,10,1) rand(10,1)];
a =
4.0000 0.4387
1.0000 0.3816
2.0000 0.7655
1.0000 0.7952
1.0000 0.1869
5.0000 0.4898
4.0000 0.4456
2.0000 0.6463
5.0000 0.7094
1.0000 0.7547
[uniqueID,~,uniqueInd]=unique(a(:,1));
[uniqueID accumarray(uniqueInd,a(:,2))./accumarray(uniqueInd,1)]
ans =
1.0000 0.5296
2.0000 0.7059
4.0000 0.4422
5.0000 0.5996
If your matrix is called a, try
>> accumarray(grp2idx(a(:,1)),a(:,2),[],#mean)
ans =
1.6957
0.5786
0.1986
0.16295
0.07675
0.0583
0.0478
0.0324
Note that grp2idx is part of Statistics Toolbox. If you don't have that, you can use the unique command to get the same results.