How to find max value and reduce it from other arrays

1 回表示 (過去 30 日間)
Tiffan 2017 年 5 月 26 日

Consider matrix input:
input = [
1 3 50 60
1 1 40 60
1 4 30 60
2 3 40 50
2 4 30 50
2 1 50 50
2 9 10 50
3 2 20 0
3 9 30 0
3 5 40 0
4 2 50 -20
4 2 60 -20
4 1 10 -20
4 1 80 -20
4 8 80 -20
];
I want to calculate the difference between third and forth column in matrix input according to the two conditions:
1st: If the value in the forth column is positive, then divide this value to the number of unique ID (in the first column) and then differ by the third column.
2st: If the value in the forth column is negative, then find the maximum from the third column (for every unique ID) and then differ that value with it. And repeat the rest of arrays in column forth for others. In the event that there are more than one maximum value (same value) just consider one of them.
The output matrix should be like followings:
out = [
1 3 50 60 30
1 1 40 60 20
1 4 30 60 10
2 3 40 50 27.5
2 4 30 50 17.5
2 1 50 50 37.5
2 9 10 50 -2.5
3 2 20 0 20
3 9 30 0 30
3 5 40 0 40
4 2 50 -20 50
4 2 60 -20 60
4 1 10 -20 10
4 1 80 -20 100
4 8 80 -20 80
];
The following code is for situation when we count number of IDs and calculate difference with dividing by that.
a = input;
ii = accumarray(a(:,1),1);
out1 = [a(:,1:2),a(:,3) - a(:,end)./ii(a(:,1))];
1 件のコメント-1 件の古いコメントを表示-1 件の古いコメントを非表示
Tiffan 2017 年 5 月 26 日
Thank you @Azzi for your comment. We should not divide by 1. We should count how many 1 is there then divide by that (In your example the correct calculation is abs(60/3-50) = 30. We devided by 3 because there are three 1

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

採用された回答

Azzi Abdelmalek 2017 年 5 月 26 日
A = [
1 3 50 60
1 1 40 60
1 4 30 60
2 3 40 50
2 4 30 50
2 1 50 50
2 9 10 50
3 2 20 0
3 9 30 0
3 5 40 0
4 2 50 -20
4 2 60 -20
4 1 10 -20
4 1 80 -20
4 8 80 -20
];
id=A(:,4)>=0
jd=A(:,4)<0
aa=A(id,:);
bb=A(jd,:);
[ii,jj,kk]=unique(aa(:,1),'stable')
b=aa(:,3)-cell2mat(accumarray(kk,(1:numel(kk)),[],@(x){aa(x,4)/numel(x)}))
A(id,5)=b
[ii,jj,kk]=unique(bb(:,1),'stable')
ix=cell2mat(accumarray(kk,1:numel(kk),[],@(x) {x(find(bb(x,3)==max(bb(x,3)),1))}))
c=A(jd,:);
c(:,5)=c(:,3)
c(ix,5)=c(ix,3)-c(ix,4)
A(jd,5)=c(:,5);

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

その他の回答 (1 件)

Andrei Bobrov 2017 年 5 月 27 日

g = findgroups(M(:,1));
ia = accumarray(g,1);
out = M;
out(:,5) = out(:,3) - out(:,4)./ia(g);
t = M(:,4) < 0;
out(t,5) = out(t,3);
idx = splitapply(@varmax,M(:,3),g);
ii = idx + cumsum([0;ia(1:end-1)]);
ii = ii(M(ii,4) < 0);
out(ii,5) = out(ii,3) - out(ii,4);
where varmax:
function ii = varmax(x)
ii = find(max(x) == x);
ii = ii(randperm(numel(ii),1));
end
for MATLAB <= R2016a
ia = accumarray(M(:,1),1);
out = M;
out(:,5) = out(:,3) - out(:,4)./ia(g);
t = M(:,4) < 0;
out(t,5) = out(t,3);
idx = accumarray(M(:,1),M(:,3),[],@varmax);
ii = idx + cumsum([0;ia(1:end-1)]);
ii = ii(M(ii,4) < 0);
out(ii,5) = out(ii,3) - out(ii,4)
where varmax:
function ii = varmax(x)
ii = find(max(x) == x);
ii = ii(randperm(numel(ii),1));
end

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

カテゴリ

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

Community Treasure Hunt

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

Start Hunting!

Translated by