Effacer les filtres
Effacer les filtres

Can I get rid of this for loop?

2 vues (au cours des 30 derniers jours)
Ryan
Ryan le 18 Mar 2016
Modifié(e) : Stephen23 le 18 Mar 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!

Réponse acceptée

Stephen23
Stephen23 le 18 Mar 2016
Modifié(e) : Stephen23 le 18 Mar 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

Plus de réponses (2)

Star Strider
Star Strider le 18 Mar 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 le 18 Mar 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.

Catégories

En savoir plus sur Creating and Concatenating Matrices dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by