I want to group the columns of the matrix A which have the same value for the third line in Matlab - 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).

Related

Enlarge matrix repeating its values [duplicate]

This question already has answers here:
Replicate matrix one row at a time [duplicate]
(2 answers)
Closed 6 years ago.
I need to enlarge a matrix A to a matrix B with size n times the size of A. The values must be repeated, eg:
A size 2x3, n = 3, leads to B size 6x9:
Sample values:
A =
1 2 3
4 5 6
Results with:
B =
1 1 1 2 2 2 3 3 3
1 1 1 2 2 2 3 3 3
1 1 1 2 2 2 3 3 3
4 4 4 5 5 5 6 6 6
4 4 4 5 5 5 6 6 6
4 4 4 5 5 5 6 6 6
What is the fastest way to achieve that in Matlab?
There is also the Kronecker Tensor Product (kron) function:
n = 3;
B = kron(A,ones(n));
B =
1 1 1 2 2 2 3 3 3
1 1 1 2 2 2 3 3 3
1 1 1 2 2 2 3 3 3
4 4 4 5 5 5 6 6 6
4 4 4 5 5 5 6 6 6
4 4 4 5 5 5 6 6 6
If you have the Image Processing Toolbox you can easily do this using imresize with nearest neighbor interpolation.
A = [1 2 3; 4 5 6];
% Repeat each element 3 times in each direction
B = imresize(A, 3, 'nearest');
% 1 1 1 2 2 2 3 3 3
% 1 1 1 2 2 2 3 3 3
% 1 1 1 2 2 2 3 3 3
% 4 4 4 5 5 5 6 6 6
% 4 4 4 5 5 5 6 6 6
% 4 4 4 5 5 5 6 6 6
If you don't have the Image Processing Toolbox, you can use interp2 with nearest neighbor interpolation to do something similar.
scaleFactor = 3;
[xx,yy] = meshgrid(linspace(1, size(A, 2), size(A, 2) * scaleFactor), ...
linspace(1, size(A, 1), size(A, 1) * scaleFactor));
B = interp2(A, xx, yy, 'nearest');

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),:)

sort multiple columns according to particular order

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

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