reshape matrix without loop
2 ビュー (過去 30 日間)
古いコメントを表示
I want to change the matrix such that the first and second array are the panes of the final matrix.
That is I want to transform this
1 1 5
1 2 6
1 3 7
2 1 8
2 2 9
into this
5 6 7
8 9 NaN
I know how to do it brute force with a loop:
d = [1 1 1 2 2]';
g = [1 2 3 1 2]';
v = [5 6 7 8 9]';
A = [d g v];
for i = 1:max(d)
M1=A(d == i,:);
for j = 1 :max(g)
M2=M1(M1(:,2) == j,:);
B(i,j) =mean(M2(:,3));
end
end
However, are there more time-saving ways?
1 件のコメント
採用された回答
Jos (10584)
2018 年 8 月 9 日
A simple one-liner would do, I think, letting accumarray do all the work:
A = [ 1 1 5
1 2 6
1 3 7
2 1 8
2 2 9 ]
B = accumarray(A(:,[1 2]), A(:,3), [], [], NaN)
% 5 6 7
% 8 9 NaN
3 件のコメント
Rik
2018 年 8 月 9 日
True, except for the requirement of calculating the mean for any duplicate, so it becomes this:
A = [ 1 1 5
1 2 6
1 3 7
2 1 8
2 2 7
2 2 9 ]
B = accumarray(A(:,[1 2]), A(:,3), [], @mean, NaN)
その他の回答 (2 件)
Fangjun Jiang
2018 年 8 月 7 日
a=[ 1 1 5
1 2 6
1 3 7
2 1 8
2 2 9];
MatrixSize=max(a(:,1:2));
b=nan(MatrixSize);
b(sub2ind(MatrixSize,a(:,1),a(:,2)))=a(:,3)
Rik
2018 年 8 月 7 日
編集済み: Rik
2018 年 8 月 7 日
I now wrote it with accumarray, without needing the call to unique. I also added a part that handles any empty positions (I removed the 1,2 position).
d = [1 1 2 2 2]';
g = [1 3 1 2 2]';
v = [5 7 8 9 7]';
%pre-allocate correct size output as NaN
out=NaN(max(d),max(g));
%convert subs to linear indices
ind=sub2ind(size(out),d,g);
%compute mean for each position (taking care of duplicates
means = accumarray(ind,v,[],@nanmean);
%paste into output array
out(1:numel(means))=means;
%take care of skipped values (replace 0 by NaN)
%(ismembc is way faster than ismember, and works best with 2 sorted arrays)
missing=find(~ismembc(1:numel(means),sort(ind)));
out(missing)=NaN;
Original post:
I'm assuming you want to calculate the mean for any duplicates. The code to remove duplicates could be further optimized.
d = [1 1 1 2 2]';
g = [1 2 3 1 2]';
v = [5 6 7 8 9]';
%pre-allocate correct size output as NaN
out=NaN(max(d),max(g));
%convert subs to linear indices
ind=sub2ind(size(out),d,g);
%sort indices and values
[ind,order]=sort(ind);v=v(order);
%check for double assignments
while any(diff(ind)==0)
%compute mean
current_index=ind(find(diff(ind)==0,1));
L=ind==current_index;
new_value=mean(v(L));
%remove old values and put back the new one
ind(L)=[];v(L)=[];
ind=[ind;current_index];v=[v;new_value]; %#ok<AGROW>
end
%write to matrix
out(ind)=v;
6 件のコメント
Rik
2018 年 8 月 8 日
You're welcome. If this solves your issue better than Fangjun's answer, you can un-accept that one and accept this one. (he will still keep the reputation points)
参考
カテゴリ
Help Center および File Exchange で Performance and Memory についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!