Asked by Tiffan
on 26 May 2017

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))];

Answer by Azzi Abdelmalek
on 26 May 2017

Accepted Answer

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);

Sign in to comment.

Answer by Andrei Bobrov
on 27 May 2017

Edited by Andrei Bobrov
on 27 May 2017

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

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 1 Comment

## Tiffan (view profile)

Direct link to this comment:https://it.mathworks.com/matlabcentral/answers/342128-how-to-find-max-value-and-reduce-it-from-other-arrays#comment_457057

Sign in to comment.