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');
Related
Given the matrix I = [1,2;3,4], I would like to duplicate the elements to create a matrix I2 such that:
I2 = [1 1 1 2 2 2
1 1 1 2 2 2
1 1 1 2 2 2
3 3 3 4 4 4
3 3 3 4 4 4
3 3 3 4 4 4]
Other than using repmat, what other methods or functions are available?
Use kron:
>> N = 3 %// Number of times to replicate a number in each dimension
>> I = [1,2;3,4];
>> kron(I, ones(N))
ans =
1 1 1 2 2 2
1 1 1 2 2 2
1 1 1 2 2 2
3 3 3 4 4 4
3 3 3 4 4 4
3 3 3 4 4 4
This probably deserves some explanation in case you're not aware of what kron does. kron stands for the Kronecker Tensor Product. kron between two matrices A of size m x n and B of size p x q creates an output matrix of size mp x nq such that:
Therefore, for each coefficient in A, we take this value, multiply it with every value in the matrix B and we position these matrices in the same order as we see in A. As such, if we let A = I, and B be the 3 x 3 matrix full of ones, you thus get the above result.
Using indexing:
I = [1, 2; 3, 4]; %// original matrix
n = 3; %// repetition factor
I2 = I(ceil(1/n:1/n:size(I,1)), ceil(1/n:1/n:size(I,2))); %// result
One-liner with bsxfun -
R = 3; %// Number of replications
I2 = reshape(bsxfun(#plus,permute(I,[3 1 4 2]),zeros(R,1,R)),R*size(I,1),[])
Sample run -
I =
3 2 5
9 8 9
I2 =
3 3 3 2 2 2 5 5 5
3 3 3 2 2 2 5 5 5
3 3 3 2 2 2 5 5 5
9 9 9 8 8 8 9 9 9
9 9 9 8 8 8 9 9 9
9 9 9 8 8 8 9 9 9
I have a matrix for which I extract each column and do repmat function for each of them to build another matrix. Since i I have to do this for a large number of vectors(each column of my first matrix) it takes so long(relative to which I expect). If I do this for the whole matrix and then do something to build them, does it takes less time?
Consider this as an example:
A=[1 4 7;2 5 8;3 6 9]
I want to produce these
A1=[1 2 3 1 2 3 1 2 3
1 2 3 1 2 3 1 2 3
1 2 3 1 2 3 1 2 3]
A2=[4 5 6 4 5 6 4 5 6
4 5 6 4 5 6 4 5 6
4 5 6 4 5 6 4 5 6]
A3=[7 8 9 7 8 9 7 8 9
7 8 9 7 8 9 7 8 9
7 8 9 7 8 9 7 8 9]
As an alternative to #thewaywewalk's answer and using kron and repmat:
clear
A=[1 4 7;2 5 8;3 6 9];
B = repmat(kron(A',ones(3,1)),1,3);
A1 = B(1:3,:)
A2 = B(4:6,:)
A3 = B(7:end,:)
Which results in the following:
A1 =
1 2 3 1 2 3 1 2 3
1 2 3 1 2 3 1 2 3
1 2 3 1 2 3 1 2 3
A2 =
4 5 6 4 5 6 4 5 6
4 5 6 4 5 6 4 5 6
4 5 6 4 5 6 4 5 6
A3 =
7 8 9 7 8 9 7 8 9
7 8 9 7 8 9 7 8 9
7 8 9 7 8 9 7 8 9
Or as #Divakar pointed out, it would be advisable to create a single 3D array and store all your data in it (general solution):
n = 3; %// # of times you want to repeat the arrays.
A=[1 4 7;2 5 8;3 6 9];
B = repmat(kron(A',ones(n,1)),1,n);
C = zeros(n,n*size(A,2),3);
C(:,:,1) = B(1:n,:);
C(:,:,2) = B(n+1:2*n,:);
C(:,:,3) = B(2*n+1:end,:);
Try if this fits your needs:
A = [1 4 7;2 5 8;3 6 9];
n = 3; %// size(A,1)
cellArrayOutput = arrayfun(#(x) repmat( A(:,x).',n,n ), 1:size(A,2), 'uni',0)
instead of different variable names, everything is stored in a cell array.
if you insist on different names, I'd recommend to use structs:
A = [1 4 7;2 5 8;3 6 9];
n = 3;
structOutput = struct;
for ii = 1:size(A,2)
structOutput.(['A' num2str(ii)]) = repmat( A(:,ii).', n, n );
end
which gives you:
>> structOutput.A1
ans =
1 2 3 1 2 3 1 2 3
1 2 3 1 2 3 1 2 3
1 2 3 1 2 3 1 2 3
and so on.
I don't expect to much performance plus, you should share your full code for further help.
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.
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
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).