Sorting from highest to lowest for a particular column

2 Ansichten (letzte 30 Tage)
Gazi Iqbal
Gazi Iqbal am 5 Apr. 2019
Bearbeitet: per isakson am 7 Apr. 2019
I have A (3*5) matrix. I have B(14*6) matrix.
Now I want C (14*5) matrix from A and B in such a way that column 2 and 3 for each row of matrix B will be replaced by corresponding cell value of A.
For example – column 2 and 3 of 1st row of B is 1 and 4. Then we need to find the value of A(1,4) which is 10. This 10 will be second column value for 1st row of matrix C.
C(:,1)= B(:,1) ; C(:,2) = from above condition; C(:,3) = B(:,4); C(:,4) = B(:,5) ; C(:,5) = B(:,6)
Eventually, I want matrix D(14*5) from C with the second column value sorted from highest to lowest. Then all the rows in column 1, 3, 4, and 5 will be according to corresponding second column.
Can anyone please help me how to get this D matrix from A and B? I have attached A, B, C, and D matrix here for the clarification.
My B matrix row number is much larger in real case. I just made it smaller here to simplify the problem. Matrix A (3*5) is fixed.
Thanks in advance.
A=[13 12 11 10 3
13 9 8 7 2
13 6 5 4 1];
B=[1 1 4 0 3 2
2 1 2 2 0 2
3 1 2 0 5 0
4 2 2 3 2 0
5 3 5 3 0 2
6 3 4 0 0 5
7 2 5 3 2 0
8 2 4 0 3 0
9 2 3 0 2 3
10 3 2 0 3 2
11 3 3 0 0 5
12 1 3 0 5 0
13 1 1 1 2 2
14 1 5 0 2 2];
C=[1 10 0 3 2
2 12 2 0 2
3 12 0 5 0
4 9 3 2 0
5 1 3 0 2
6 4 0 0 5
7 2 3 2 0
8 7 0 3 0
9 8 0 2 3
10 6 0 3 2
11 5 0 0 5
12 11 0 5 0
13 13 1 2 2
14 3 0 2 2];
D=[13 13 1 2 2
2 12 2 0 2
3 12 0 5 0
12 11 0 5 0
1 10 0 3 2
4 9 3 2 0
9 8 0 2 3
8 7 0 3 0
10 6 0 3 2
11 5 0 0 5
6 4 0 0 5
14 3 0 2 2
7 2 3 2 0
5 1 3 0 2];

Akzeptierte Antwort

Stephen23
Stephen23 am 5 Apr. 2019
Bearbeitet: Stephen23 am 5 Apr. 2019
Simpler and no loops required with sub2ind:
>> X = sub2ind(size(A),B(:,2),B(:,3));
>> C = [B(:,1),A(X),B(:,4:end)]
C =
1 10 0 3 2
2 12 2 0 2
3 12 0 5 0
4 9 3 2 0
5 1 3 0 2
6 4 0 0 5
7 2 3 2 0
8 7 0 3 0
9 8 0 2 3
10 6 0 3 2
11 5 0 0 5
12 11 0 5 0
13 13 1 2 2
14 3 0 2 2
>> D = sortrows(C,-2)
D =
13 13 1 2 2
2 12 2 0 2
3 12 0 5 0
12 11 0 5 0
1 10 0 3 2
4 9 3 2 0
9 8 0 2 3
8 7 0 3 0
10 6 0 3 2
11 5 0 0 5
6 4 0 0 5
14 3 0 2 2
7 2 3 2 0
5 1 3 0 2
  3 Kommentare
Stephen23
Stephen23 am 6 Apr. 2019
@Gazi Iqbal: note that in your example code
B = nan(size(A,1),size(A,2));
for i=1:size(A,1)
B(:,1:end) = A(:,1:end);
end
the loop is totally superlfluous, because the indexing (:,1:end) already access all rows of those arrays. How to use indexing on arrays is a basic MATLAB concept you need to learn:
I do not understand your description, e.g. " then the other elements of that row should be 0" what are the "other elements" ? Probably the simplest is if you provide the expected output using your example data.
Gazi Iqbal
Gazi Iqbal am 6 Apr. 2019
Hi Stephen.
Sorry, I mistakenly wrote “B(:,1:end)” instead of “B(i,1:end)”..Similarly for A(i,1:end)
B = nan(size(A,1), size(A,2));
for i=1:size(A,1)
B(i,1:end) = A(i,1:end);
end
For simplicity, Suppose my A matrix is 14*3. I want matrix B(14*3) based on that two conditions.
I want to keep assigning A into B. 1st row will get 1st priority.. and then 2nd row, 3rd row..etc....
It’s kind of checking summation of each column every time before assigning a new row from A into B. If that summation is already 25, then assign 0 in the rest of the elements of that column. But if it is not 25, then keep assigning from A (assignment value ranges 0 to 5 and integer), but we just want to make sure that summation of each row cannot be > 5
For example :
From row 1 to 12 of attached matrix A, both conditions (sum of all the previous elements of each colum is <=25; and sum of all the elements of each row is <=5) were satisfied. So I keep A[1:12,:]= B[1:12,:]
But for row 13 in A,
A(13,1:end)= [3 2 0] …but to satisfy summation of each column <=25 , I had to make it in B as B(13,1:end)= [5 0 0]
Here, I cannot assign anything in 2nd column of B, because the summation of previous elements of this column is already 25,
and in 3rd column it was already 0 in A. So I need to keep it 0. We could have assign any value here, as summation si till <=25 for this column. But as I said We want to make sure each row get maximum preference in their assignment. Since they had 0 in 3rd column of A, so I put 0 in matrix B as well.
The only thing I can do is assign 5 in 1st column, because if I assign 5 here, still summation of previous elements of Column 1 is <=25 . For example if it was [2 2 0] in A for this row, I will need to assign [4 0 0] in B.
So after assigning first element as 5, then the rest of the element is 0(zero) in row 13, as summation of each row cannot be >5.
Similarly, sum(A(1:9,2))= 25, so I need to make next 4 elements of this column 2 is o(zero) in the B matrix, as summation of each column cannot be >25
Hope this time I made it clear. Sorry for my poor English. My new input matrix A and output matrix B is given here.
Thank you so much for your time.
A=[1 2 2
2 0 2
0 5 0
0 5 0
0 3 2
3 2 0
0 2 3
0 3 0
0 3 2
0 0 5
0 0 5
0 2 2
3 2 0
3 0 2];
B=[1 2 2
2 0 2
0 5 0
0 5 0
0 3 2
3 2 0
0 2 3
0 3 0
0 3 2
0 0 5
0 0 5
2 0 2
5 0 0
3 0 2];

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

per isakson
per isakson am 5 Apr. 2019
Bearbeitet: per isakson am 5 Apr. 2019
Try this
%%
C1 = nan( size( B(:,1:end-1) ) );
%%
for rr = 1 : size(B,1)
C1( rr, 2 ) = A( B(rr,2), B(rr,3) );
end
C1(:,[1,3,4,5]) = B(:,[1,4,5,6]);
%%
D1 = sortrows( C1, 2, 'descend' );
The names C1 and D1 to avoid overwriting C and D
  9 Kommentare
per isakson
per isakson am 7 Apr. 2019
Bearbeitet: per isakson am 7 Apr. 2019
The sum of the rows in this particular A, satisfy sum(A(rr,:)) <= 5 for all rr. However, the algorithm cannot be based on that - or ?
I'm prepared to throw in the towel
%%
csA2 = cumsum( A, 2 );
is_row_cumsum_gt_5 = csA2 > 5;
%
csA1 = cumsum( A, 1 );
is_col_cumsum_gt_25 = csA1 > 25;
%%
B1 = A;
for rr = 2 : size( A, 1 )
% change what's needed to fullfil the conditions
% I envision a lot of edge cases resulting in as
% many if-statements, which in turn requires a lot
% of testing
end
Gazi Iqbal
Gazi Iqbal am 7 Apr. 2019
Bearbeitet: per isakson am 7 Apr. 2019
Thank you so much for your reply.
You’re right. In my real input matrix, sum(A(rr,:)) <= 5 for all rr
If I want to focus only on sum(B1(:,jj)) <= 25 for all jj part, then I tried following :
csA1 = cumsum( A, 1 );
is_col_cumsum_gt_25 = csA1 > 25;
B1 = A;
B1(1,:) = A(1,:);
for i=2:size(A,1)
for j= 1:size(A,2)
if is_col_cumsum_gt_25(i,j) == 0
p = 25-sum(B1(1:i-1,j));
if p >5
B1(i,j) = A(i,j);
else
B1(i,j) = min(A(i,j),p);
end
else
B1(i,j) = 0;
end
end
end
Above code works fine for previous input matrix A. but if my input matrix A is like below:
A=[ 1 2 2
2 0 2
0 5 0
0 5 0
0 3 2
3 2 0
5 2 3
5 3 0
0 3 2
5 0 5
0 0 5
3 2 2
3 2 0
3 0 2];
Then above code doesn’t give the result what I want. Because from this A matrix, B1[13,1] was supposed to be 1, but it is 0 from above code. And I know why this is happening. Because csA1(13,1) = 27 and that’s why is_col_cumsum_gt_25(13,1) ==1 which eventually makes B1(13,1) =0 from above code. Do you have any suggestions to solve this issue?
I’m grateful to you for all these replies. Hopefully, this is my last question for this problem.

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Creating and Concatenating Matrices finden Sie in Help Center und File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by