Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Element-wise Matrix Replication in MATLAB

I have a 3 dimensional matrix. I want to replicate the matrix of size 8x2x9 to a specified number of times in the third dimension given by a vector say [3, 2, 1, 1, 5, 4, 2, 2, 1] so that the resultant matrix is of size 8x2x21. Is there any built-in MATLAB function (I'm running version 2014a) to do this similar to the newer repelem function, for matrices?

A simple example of what I need:

% Input:
A(:,:,1) = [1 2; 1 2];
A(:,:,2) = [2 3; 2 3];

% Function call:
A = callingfunction(A, 1, 1, [1 2]);

% Output:
A(:,:,1) = [1 2; 1 2];
A(:,:,2) = [2 3; 2 3];
A(:,:,3) = [2 3; 2 3];
like image 617
Santhan Salai Avatar asked Mar 20 '15 15:03

Santhan Salai


People also ask

How do you multiply a matrix element-wise in MATLAB?

Multiply Row and Column Vectors The result is a 4-by-3 matrix, where each (i,j) element in the matrix is equal to a(j). *b(i) : a = [ a 1 a 2 a 3 ] , b = [ b 1 b 2 b 3 b 4 ] , a . * b = [ a 1 b 1 a 2 b 1 a 3 b 1 a 1 b 2 a 2 b 2 a 3 b 2 a 1 b 3 a 2 b 3 a 3 b 3 a 1 b 4 a 2 b 4 a 3 b 4 ] .

How do you repeat an array of elements in MATLAB?

u = repelem( v , n ) , where v is a scalar or vector, returns a vector of repeated elements of v . If n is a scalar, then each element of v is repeated n times. The length of u is length(v)*n .

How do you repeat a matrix in MATLAB?

B = repmat( A , r ) specifies the repetition scheme with row vector r . For example, repmat(A,[2 3]) returns the same result as repmat(A,2,3) .


1 Answers

For R2015a and newer...

According to the documentation for repelem (first introduced in version R2015a), it can operate on matrices as well. I believe the following code should accomplish what you want (I can't test it because I have an older version):

newMat = repelem(mat, 1, 1, [3 2 1 1 5 4 2 2 1]);

For pre-R2015a versions...

You can use one of the approaches from this question to replicate an index into the third dimension, then simply index your matrix with that. For example (adapting Divakar's solution):

vals = 1:size(mat, 3);
clens = cumsum([3 2 1 1 5 4 2 2 1]);
index = zeros(1, clens(end));
index([1 clens(1:end-1)+1]) = diff([0 vals]);
newMat = mat(:, :, cumsum(index));

You can then generalize this into a function to operate on multiple dimensions like repelem does:

function A = my_repelem(A, varargin)

  index = cell(1, nargin-1);
  for iDim = 1:nargin-1
    lens = varargin{iDim};
    if isscalar(lens)
      if (lens == 1)
        index{iDim} = ':';
        continue
      else
        lens = repmat(lens, 1, size(A, iDim));
      end
    end
    vals = 1:size(A, iDim);
    clens = cumsum(lens);
    index{iDim} = zeros(1, clens(end));
    index{iDim}([1 clens(1:end-1)+1]) = diff([0 vals]);
    index{iDim} = cumsum(index{iDim});
  end
  A = A(index{:});

end

And for your sample data, you would use it like so:

>> A(:,:,1) = [1 2; 1 2];
>> A(:,:,2) = [2 3; 2 3];
>> A = my_repelem(A, 1, 1, [1 2])

A(:,:,1) =

     1     2
     1     2

A(:,:,2) =

     2     3
     2     3

A(:,:,3) =

     2     3
     2     3
like image 91
gnovice Avatar answered Sep 25 '22 14:09

gnovice