简体   繁体   English

在Matlab中的每第n行之后,在矩阵中的每个序列中插入一行到另一个矩阵

[英]Inserting One Row Each Time in a Sequence from Matrix into Another Matrix After Every nth Row in Matlab

I have matrix A and matrix B. Matrix A is 100*3. 我有矩阵A和矩阵B.矩阵A是100 * 3。 Matrix B is 10*3. 矩阵B是10 * 3。 I need to insert one row from matrix B each time in a sequence into matrix A after every 10th row. 我需要每次在一个序列中将矩阵B中的一行插入到每第10行之后的矩阵A中。 The result would be Matrix A with 110*3. 结果将是Matrix A,110 * 3。 How can I do this in Matlab? 我怎样才能在Matlab中做到这一点?

Here's an index-based approach: 这是一种基于索引的方法:

%//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 approach sans magic numbers: 只是为了好玩,这里的方法与魔术数字相同:

%//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;

For canonical purposes, here's how you'd do it via loops. 对于规范目的,这是你如何通过循环来做到这一点。 This is a bit inefficient since you're mutating the array at each iteration, but it's really simple to read. 这是有点低效的,因为你在每次迭代时都会改变数组,但它的读取非常简单。 Given that your two matrices are stored in A (100 x 3) and B (10 x 3), you would do: 鉴于您的两个矩阵存储在A (100 x 3)和B (10 x 3)中,您可以:

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

At each iteration, we pick out 10 rows of A and 1 row of B and we concatenate these 11 rows onto out . 在每次迭代中,我们选出10行A和1行B然后将这11行连接到out This happens 10 times, resulting in 330 rows with 3 columns. 这种情况发生了10次,导致330行,3列。

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. 感谢@Divakar指出我以前的错误。

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

Solution Code 解决方案代码

Here's an implementation based on logical indexing also known as masking and must be pretty efficient when working with large arrays - 这是一个基于logical indexing的实现,也称为masking ,在处理大型数组时必须非常高效 -

%// 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 #1: A as 100 x 3 and B as 10 x 3 案例#1: A100 x 3B10 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 #2: A as 100000 x 3 and B as 10000 x 3 情况#2: A100000 x 3B10000 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.

Please note that num_iter was different for these two cases, as the idea was to keep the runtimes > 1 sec mark to compensate for tic-toc overheads. 请注意,这两种情况的num_iter不同,因为我们的想法是保持运行时间> 1秒标记以补偿tic-toc开销。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM