Filter löschen
Filter löschen

Can I get rid of this for loop?

2 Ansichten (letzte 30 Tage)
Ryan
Ryan am 18 Mär. 2016
Bearbeitet: Stephen23 am 18 Mär. 2016
I have a matrix that has 3 columns that consist of -1, 0, and 1 (let's call them the "level columns"), and a fourth column that contains real numbers (call it the "data column"). For the level columns, I want to find the average of the "-1", "0", and "1" terms in the data column. So for the following matrix,
-1 -1 0 837
-1 0 -1 880
-1 0 1 879
-1 1 0 864
0 -1 -1 834
0 -1 1 833
0 0 0 874
0 0 0 875
0 0 0 876
0 1 -1 860
0 1 1 859
1 -1 0 829
1 0 -1 872
1 0 1 874
1 1 0 856
the -1 average for column 1 would be 865. Is there a way that I can do that all at once, for each level column, and each level column value? Right now, I loop over the level columns and do this:
[mean(testMat(testMat(:,col) == -1,4)) mean(testMat(testMat(:,col) == 0,4)) mean(testMat(testMat(:,col) == 1,4))]
Is there a better way?
Thanks!

Akzeptierte Antwort

Stephen23
Stephen23 am 18 Mär. 2016
Bearbeitet: Stephen23 am 18 Mär. 2016
You cannot get rid of the for loop, but you can hide it inside a cellfun call. Note that my answer works for any number of columns, unlike the other solutions.
M = [...
-1 -1 0 837
-1 0 -1 880
-1 0 1 879
-1 1 0 864
0 -1 -1 834
0 -1 1 833
0 0 0 874
0 0 0 875
0 0 0 876
0 1 -1 860
0 1 1 859
1 -1 0 829
1 0 -1 872
1 0 1 874
1 1 0 856 ];
%
[~,~,X] = cellfun(@unique,num2cell(M(:,1:end-1),1),'Uni',0);
N = cellfun(@(s)accumarray(s,M(:,end),[],@mean),X, 'Uni',0);
out = [N{:}]
creates this output matrix, where the rows correspond to [-1;0;1]:
>> out
out =
865 833.25 861.5
858.71 875.71 858.71
857.75 859.75 861.25

Weitere Antworten (2)

Star Strider
Star Strider am 18 Mär. 2016
I would use three concatenated accumarray calls:
M = [-1 -1 0 837
-1 0 -1 880
-1 0 1 879
-1 1 0 864
0 -1 -1 834
0 -1 1 833
0 0 0 874
0 0 0 875
0 0 0 876
0 1 -1 860
0 1 1 859
1 -1 0 829
1 0 -1 872
1 0 1 874
1 1 0 856];
Result = [accumarray(M(:,1)+2, M(:,4), [], @mean), accumarray(M(:,2)+2, M(:,4), [], @mean), accumarray(M(:,3)+2, M(:,4), [], @mean)];
Result =
865 833.25 861.5
858.71 875.71 858.71
857.75 859.75 861.25
Here, the columns correspond to those in ‘M(:,1:3)’ and the rows correspond to ‘[-1; 0; 1]’ respectively.

Image Analyst
Image Analyst am 18 Mär. 2016
If you have the Statistics and Machine Learning Toolbox, you can use grpstats(), but I don't know if it would be any more compact that what you're already doing.

Kategorien

Mehr zu Creating and Concatenating Matrices finden Sie in Help Center und File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by