How to efficiently compare two matrix to get a single reference value?

1 回表示 (過去 30 日間)
balandong
balandong 2019 年 1 月 15 日
コメント済み: Rik 2019 年 1 月 17 日
May I know how make the following code more efficient and compact. Specifically, I want to reduce the line
ConfMat (logical (((TrueVal==xx) .*(Predicted==xx))))=xx;
Here are the complete code and its output
TrueVal= [1 1 1 2 2 2 3 3 3 1 2]';
Predicted=[1 2 3 1 2 3 1 2 3 3 2]';
ConfMat = single(ones(length(TrueVal), 1));
ConfMat (logical (((TrueVal==1) .*(Predicted==2))))=4;
ConfMat (logical (((TrueVal==1) .*(Predicted==3))))=7;
ConfMat (logical (((TrueVal==2) .*(Predicted==1))))=2;
ConfMat (logical (((TrueVal==2) .*(Predicted==2))))=5;
ConfMat (logical (((TrueVal==2) .*(Predicted==3))))=8;
ConfMat (logical (((TrueVal==3) .*(Predicted==1))))=3;
ConfMat (logical (((TrueVal==3) .*(Predicted==2))))=6;
ConfMat (logical (((TrueVal==3) .*(Predicted==3))))=9;
% Final output
% ConfMat= [1;4;7;2;5;8;3;6;9;7;5]
Thanks in advance
  3 件のコメント
madhan ravi
madhan ravi 2019 年 1 月 15 日
Second Rik , I can't think of any solution other than that.
balandong
balandong 2019 年 1 月 15 日
Thanks both of you, I have the same idea about using for loop. I just wonder if there is an elegant ways of doing it.

サインインしてコメントする。

採用された回答

Rik
Rik 2019 年 1 月 15 日
編集済み: Rik 2019 年 1 月 15 日
I don't know if this is elegant enough for you, but it does work.
TrueVal= [1 1 1 2 2 2 3 3 3 1 2]';
Predicted=[1 2 3 1 2 3 1 2 3 3 2]';
%legend: TrueVal Predicted value
matrix=[1 2 4
1 3 7
2 1 2
2 2 5
2 3 8
3 1 3
3 2 6
3 3 9];
ConfMat = single(ones(numel(TrueVal), 1));
for n=1:size(matrix,1)
xx_TrueVal=matrix(n,1);
xx_Predicted=matrix(n,2);
L=((TrueVal==xx_TrueVal) & (Predicted==xx_Predicted));
ConfMat(L)=matrix(n,3);
end
isequal(ConfMat,single([1;4;7;2;5;8;3;6;9;7;5]))
Or maybe you think this is a more elegant method:
TrueVal= [1 1 1 2 2 2 3 3 3 1 2]';
Predicted=[1 2 3 1 2 3 1 2 3 3 2]';
% %legend: TrueVal Predicted value
% matrix=[1 2 4
% 1 3 7
% 2 1 2
% 2 2 5
% 2 3 8
% 3 1 3
% 3 2 6
% 3 3 9];
% matrix=accumarray(matrix(:,1:2),matrix(:,3),[],[],1);
matrix = [...
1 4 7
2 5 8
3 6 9];
ConfMat = single(ones(numel(TrueVal), 1));
for n_true=1:size(matrix,2)
for n_pred=1:size(matrix,1)
L=((TrueVal==n_true) & (Predicted==n_pred));
ConfMat(L)=matrix(n_true,n_pred);
end
end
clc
isequal(ConfMat,single([1;4;7;2;5;8;3;6;9;7;5]))
  3 件のコメント
balandong
balandong 2019 年 1 月 17 日
Hi Rik,
Thanks for the insight. It does look smart than my initial idea. However, the proposal by Bruno is somewhat more compact. I had to accept his answer for this.
Rik
Rik 2019 年 1 月 17 日
@balandong no problem. Both solutions have their own situation where they are the best option. It is your code, and your question, so it is on you to choose.
Just in case someone else prefers my solution, I'll keep my answer here.

サインインしてコメントする。

その他の回答 (1 件)

Bruno Luong
Bruno Luong 2019 年 1 月 15 日
TrueVal= [1 1 1 2 2 2 3 3 3 1 2]';
Predicted=[1 2 3 1 2 3 1 2 3 3 2]';
[ut,~,it] = unique(TrueVal);
[up,~,ip] = unique(Predicted);
ConfM = [1 4 7;
2 5 8;
3 6 9];
assert(size(ConfM,1)==length(ut),'ConfM must have same #rows than #TrueVal');
assert(size(ConfM,2)==length(up),'ConfM must have same #rows than #Predicted');
ConfMat = ConfM(sub2ind(size(ConfM),it,ip))
returns
ConfMat =
1
4
7
2
5
8
3
6
9
7
5
  1 件のコメント
balandong
balandong 2019 年 1 月 17 日
Dear Bruno,
Thanks for the compact answer, appreciate it

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeLegend についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by