Inserting one row each time in sequence from matrix to another matrix after every nth row in Matlab

I have matrix A and matrix B. Matrix A is 100 * 3. Matrix B is 10 * 3. I need to insert one row from matrix B each time in sequence into matrix A after every 10th row. The result will be Matrix A with 110 * 3. How can I do this in Matlab?

+3


source to share


5 answers


Here's another indexing-based approach:



n = 10;
C = [A; B];
[~, ind] = sort([1:size(A,1) n*(1:size(B,1))+.5]);
C = C(ind,:);

      

+4


source


The index approach is applied here:

%//pre-allocate output matrix
matrixC = zeros(110, 3);

%//create index array for the locations in matrixC that would be populated by matrixB
idxArr = (1:10) * 11;

%//place matrixB into matrixC
matrixC(idxArr,:) = matrixB;

%//place matrixA into matrixC
%//setdiff is used to exclude indexes already populated by values from matrixB
matrixC(setdiff(1:110, idxArr),:) = matrixA;

      



And just for fun, here's the same non-magic number approach:

%//define how many rows to take from matrixA at once
numRows = 10;

%//get dimensions of input matrices
lengthA = size(matrixA, 1);
lengthB = size(matrixB, 1);

matrixC = zeros(lengthA + lengthB, 3);
idxArr = (1:lengthB) * (numRows + 1);
matrixC(idxArr,:) = matrixB;
matrixC(setdiff(1:size(matrixC, 1), idxArr),:) = matrixA;

      

+4


source


For canonical purposes, here's how you would do it with loops. It's a bit inefficient as you mutate the array every iteration, but it's very easy to read. Given that your two matrices are stored in A

(100 x 3) and B

(10 x 3), you should:

out = [];
for idx = 1 : 10
    out = [out; A((idx-1)*10 + 1 : 10*idx,:); B(idx,:)];
end

      

In each iteration, we allocate 10 lines A

and 1 line B

, and we concatenate those 11 lines into out

. This happens 10 times, resulting in 330 rows with 3 columns.

+4


source


Just for fun ... Now with more robust test matrices!

A = ones(3, 100);
A(:) = 1:300;
A = A.'

B = ones(3, 10);
B(:) = 1:30;
B = B.' + 1000

C = reshape(A.', 3, 10, []);
C(:,end+1,:) = permute(B, [2 3 1]);
D = permute(C, [2 3 1]);
E = reshape(D, 110, 3)

      

Input:

A =

     1     2     3
     4     5     6
     7     8     9
    10    11    12
    13    14    15
    16    17    18
    19    20    21
    22    23    24
    25    26    27
    28    29    30
    31    32    33
    34    35    36
    ...

B =

   1001   1002   1003
   1004   1005   1006
   ...

      

Output:

E =

      1      2      3
      4      5      6
      7      8      9
     10     11     12
     13     14     15
     16     17     18
     19     20     21
     22     23     24
     25     26     27
     28     29     30
   1001   1002   1003
     31     32     33
     34     35     36
   ...

      

Thanks to @Divakar for pointing out my previous error.

+4


source


Solution code

Here's an implementation based on logical indexing

, also known as, masking

and should be quite efficient when dealing with large arrays -

%// Get sizes of A and B
[M,d] = size(A);
N = size(B,1);

%// Mask of row indices where rows from A would be placed
mask_idx = reshape([true(A_cutrow,M/A_cutrow) ; false(1,N)],[],1);

%// Pre-allocate with zeros: 
%// http://undocumentedmatlab.com/blog/preallocation-performance
out(M+N,d) = 0; 

%// Insert A and B using mask and ~mask
out(mask_idx,:) = A;
out(~mask_idx,:) = B;

      

Benchmarking

%// Setup inputs
A = rand(100000,3);
B = rand(10000,3);
A_cutrow = 10;

num_iter = 200; %// Number of iterations to be run for each approach

%// Warm up tic/toc.
for k = 1:50000
    tic(); elapsed = toc();
end

disp(' ------------------------------- With MASKING')
tic
for iter = 1:num_iter
    [M,d] = size(A);
    N = size(B,1);
    mask_idx = reshape([true(A_cutrow,M/A_cutrow) ; false(1,N)],[],1);

    out(M+N,d) = 0;
    out(mask_idx,:) = A;
    out(~mask_idx,:) = B;
    clear out
end
toc, clear mask_idx N M d iter

disp(' ------------------------------- With SORT')
tic
for iter = 1:num_iter
    C = [A; B];
    [~, ind] = sort([1:size(A,1) A_cutrow*(1:size(B,1))+.5]);
    C = C(ind,:);
end
toc, clear C ind iter

disp(' ------------------------------- With RESHAPE+PERMUTE')
tic
for iter = 1:num_iter
    [M,d] = size(A);
    N = size(B,1);
    C = reshape(A.', d, A_cutrow , []);
    C(:,end+1,:) = permute(B, [2 3 1]);
    D = permute(C, [2 1 3]);
    out = reshape(permute(D,[1 3 2]),M+N,[]);
end
toc, clear out D C N M d iter

disp(' ------------------------------- With SETDIFF')
tic
for iter = 1:num_iter
    lengthA = size(A, 1);
    lengthB = size(B, 1);

    matrixC = zeros(lengthA + lengthB, 3);
    idxArr = (1:lengthB) * (A_cutrow + 1);
    matrixC(idxArr,:) = B;
    matrixC(setdiff(1:size(matrixC, 1), idxArr),:) = A;
end
toc, clear matrixC idxArr lengthA lengthB

disp(' ------------------------------- With FOR-LOOP')
tic
for iter = 1:num_iter
    [M,d] = size(A);
    N = size(B,1);
    Mc = M/A_cutrow;
    out(M+N,d) = 0;
    for idx = 1 : Mc
        out( 1+(idx-1)*(A_cutrow +1): idx*(A_cutrow+1), :) = ...
        [A( 1+(idx-1)*A_cutrow : idx*A_cutrow , : ) ; B(idx,:)];
    end
    clear out
end
toc

      

Runtimes

Case number 1: A

how 100 x 3

and B

how10 x 3

 ------------------------------- With MASKING
Elapsed time is 4.987088 seconds.
 ------------------------------- With SORT
Elapsed time is 5.056301 seconds.
 ------------------------------- With RESHAPE+PERMUTE
Elapsed time is 5.170416 seconds.
 ------------------------------- With SETDIFF
Elapsed time is 35.063020 seconds.
 ------------------------------- With FOR-LOOP
Elapsed time is 12.118992 seconds.

      

Case number 2: A

how 100000 x 3

and B

how10000 x 3

 ------------------------------- With MASKING
Elapsed time is 1.167707 seconds.
 ------------------------------- With SORT
Elapsed time is 2.667149 seconds.
 ------------------------------- With RESHAPE+PERMUTE
Elapsed time is 2.603110 seconds.
 ------------------------------- With SETDIFF
Elapsed time is 3.153900 seconds.
 ------------------------------- With FOR-LOOP
Elapsed time is 19.822912 seconds.

      

Note that it num_iter

was different for these two cases as the idea was to keep the runtime stamps> 1 sec to compensate for the overhead tic-toc

.

+2


source







All Articles