sort multiple columns according to particular order - matlab

I have a matrix
A = 1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
I have 3 arrays containing the orders in which I separately want to sort the respective columns. Example I1 for column 1, I2 for column 2, ....
I1 = 5 I2 = 4 I3 = 3
4 3 2
3 2 1
2 1 5
1 5 4
After sorting the matrix A I should get:-
If only I1 is used to sort the 1st column
A = 5 1 1
4 2 2
3 3 3
2 4 4
1 5 5
If only I2 is used to sort the 2nd column
A = 1 4 1
2 3 2
3 2 3
4 1 4
5 5 5
If only I3 is used to sort the 3rd column
A = 1 1 3
2 2 2
3 3 1
4 4 5
5 5 4
If only I1,I2,I3 is used to sort the all columns
A = 5 4 3
4 3 2
3 2 1
2 1 5
1 5 4
Please suggest me how to do.

If their dimensions are all the same, this should be what you need:
A([I1 I2 I3]);
If you wish to sort columns individually, you can use this syntax:
A(:,2)=A(I2,2);
Or e.g. columns 2 and 3:
A(:,[2 3]) = [A(I2,2) A(I3,3)];

Related

Group identical rows of a matrix, together with their frequency count

The easiest way to explain the question is by an example:
>> A = [1 5; 1 5; 1 6; 1 6; 1 6; 1 6; 1 7; 2 5; 2 6; 2 6; 2 6; 2 7; 2 7; 2 8]
A =
1 5
1 5
1 6
1 6
1 6
1 6
1 7
2 5
2 6
2 6
2 6
2 7
2 7
2 8
What I want to have as output is something similar to
result =
1 6 4
1 5 2
2 6 3
2 7 2
Which means top two frequent pairs for each value in first column. So most frequent pairs came with 1 are 6 and 5 and most frequent pairs came with 2 are 6 and 7. 3rd column shows frequency of pairs.
I use matlab 2016 in linux.
You could use unique and histc to count the frequency of occurrence of each row. Then using frequency, you can proceed with your calculations.
[unique_rows,~,ind] = unique(A,'rows');
counts = histc(ind,unique(ind));
Now, you could combine the frequency count and sort them.
arr = [unique_rows,counts];
[sorted,~]=sortrows(arr,[1 -3])
sorted =
1 6 4
1 5 2
1 7 1
2 6 3
2 7 2
2 5 1
2 8 1

Remove rows containing duplicate elements

I have this example matrix:
1 2 4 5 1 3
2 3 5 6 3 4
1 2 3 4 5 6
3 2 4 6 1 5
...
I need to delete each row that contains duplicate elements. In this example I have to delete the first and second rows.
I know how to do this in a for-loop, but I don't want to use a for-loop.
Assuming A as the input matrix, you could do -
A(all(diff(sort(A,2),[],2),2),:)
Sample run -
>> A
A =
1 2 4 5 1 3
2 3 5 6 3 4
1 2 3 4 5 6
3 2 4 6 1 5
>> A(all(diff(sort(A,2),[],2),2),:)
ans =
1 2 3 4 5 6
3 2 4 6 1 5
Alternatively, if you don't mind some bsxFUN -
A(~any(sum(bsxfun(#eq,A,permute(A,[1 3 2])),2)>1,3),:)

How to sum matrix which had been already rearranged

I have some matrix :
A = [ 1 2 3 4 5 6;
1 2 3 4 5 6]
B = [ 6 5 4 3 2 1;
6 5 4 3 2 1]
C = [ 1 2 3 4 5 6;
1 2 3 4 5 6]
what is code to make this following matrix:
Result = [1 2 9 9 10 11 5 5 5 6;
1 2 9 9 10 11 5 5 5 6]
Note : Actually the above matrix is sum of 3 matrix above which had been already rearranged like as the following matrix. #sum is sum which is based on column.
1 2 3 4 5 6
1 2 3 4 5 6
6 5 4 3 2 1
6 5 4 3 2 1
1 2 3 4 5 6
1 2 3 4 5 6
And. I sum first row by first row, and second row by second row.
To do what you say above:
Result = zeros(size(A) + [0,4]);
Result(:,1:size(A,2)) = A;
Result(:,3:end-2) = Result(:,3:end-2) + B;
Result(:,5:end) = Result(:, 5:end) + C;
The point is, you can select a subregion of a matrix, and assign another matrix to it. You just have to make sure both sides of the assignment are the same shape.

MatLab:Grouping non-zero values depending of values in another vector

Lets say,we've the following two vectors:
data = [1 2 2 2 3 3 3 3 3 3 4 4 4 4 4 ];
x_axis = [1 1 1 2 2 2 3 3 3 3 3 4 4 5 5 ];
What i now want to have is to count all data values which are for example one in the x_axis ,then these values which are two etc. So the result should look like as following (which i then can represent as a histogram):
result=[5 8 16 8 8];
x_axis=[1 2 3 4 5];
This is the perfect application example for accumarray:
data = [1 2 2 2 3 3 3 3 3 3 4 4 4 4 4 ];
x_axis = [1 1 1 2 2 2 3 3 3 3 3 4 4 5 5 ];
result = accumarray(x_axis(:),data(:),[],#sum)
result =
5
8
16
8
8

I want to group the columns of the matrix A which have the same value for the third line in Matlab

For a matrix A (4 rows, 1000 columns). I want to group the columns of the matrix A which have the same value for the third line. so I must have sub matrix with a third row that contains the same value.
for example:
if:
A =
1 4 5 2 2 2 2 1 1 5
1 4 5 4 4 2 2 4 5 2
3 3 3 3 4 1 3 5 3 4
4 5 5 5 4 1 5 5 5 5
then
A1 =
1 4 5 2 2 1
1 4 5 4 2 5
3 3 3 3 3 3
4 5 5 5 5 5
A2 =
2 5
4 2
4 4
4 5
A3 =
2
2
1
1
the result can be in the form of a cell.
here's one possible hack (warning: I haven't been able to check this):
A =
1 4 5 2 2 2 2 1 1 5
1 4 5 4 4 2 2 4 5 2
3 3 3 3 4 1 3 5 3 4
4 5 5 5 4 1 5 5 5 5
specialRow=3;
unqCols = unique(A(specialRow,:));
numUnq = length(unqCols);
sepMats{numUnq}=[];
for i=1:numUnq
sepMats{i} = A(:,A(specialRow,:)==unqCols(i));
end
In the example you shown, there are 4 unique elements in the 3rd row, so you should obtain 4 submatrices, but you only show 3 ?
Here is one way:
clear all;
%data
A = [1 4 5 2 2 2 2 1 1 5;
1 4 5 4 4 2 2 4 5 2;
3 3 3 3 4 1 3 5 3 4;
4 5 5 5 4 1 5 5 5 5
]
%engine
row = 3;
b = unique(A(row,:));
r = arrayfun(#(i) A(:,A(row,:)==b(i)),1:length(b), 'UniformOutput',false);
r{:}
You can make the assignment in a single line using ACCUMARRAY:
A = [1 4 5 2 2 2 2 1 1 5;
1 4 5 4 4 2 2 4 5 2;
3 3 3 3 4 1 3 5 3 4;
4 5 5 5 4 1 5 5 5 5
];
out = accumarray(A(3,:)', (1:size(A,2)), [], #(x){A(:,x)} );
With this, out{i} contains all columns of A where the third row of A equals i (and empty in case there is no valid column).
If you want out{i} to contain columns corresponding to the i-th smallest unique value in the third row of A, you can use GRP2IDX from the statistics toolbox first:
[idx,correspondingEntryInA] = grp2idx(A(3,:)'); %'#
out = accumarray(idx, (1:size(A,2)), [], #(x){A(:,x)} );
Here, out{i} contains the columns corresponding to correspondingEntryInA(i).