Any vectorized solution is likely not going to be as simple as your for loop solution, and might actually be less efficient (edit: see timing tests below). However, if you're curious, vectorizing an indexing operation like this generally involves converting your desired indices from subscripts to linear indices. Normally you can do this using sub2ind
, but since you're selecting entire rows it may be more efficient to calculate the index yourself.
Here's a solution that takes advantage of implicit expansion in newer versions of MATLAB (R2016b and later):
[R, C, D] = size(mat1);
index = rows_to_copy+R.*(0:(C-1)).'+R*C.*(0:(D-1));
mat2(1, :, :) = reshape(mat1(index), 1, C, D);
Note that if you don't really need all the extra space full of NaN
values in mat2
, you can make your result more compact by just concatenating all the rows into a 2-D matrix instead:
>> mat2 = mat1(index).'
mat2 =
95 41 2 19 44
38 31 93 27 27
49 10 72 91 49
And if you're still using an older version of MATLAB without implicit expansion, you can use bsxfun
instead:
index = bsxfun(@plus, rows_to_copy+R*C.*(0:(D-1)), R.*(0:(C-1)).');
I ran some tests using timeit
(R2018a, Windows 7 64-bit) to see how the loop and indexing solutions compared. I tested 3 different scenarios: increasing row size, increasing column size, and increasing page size (third dimension) for mat1
. The rows_to_copy
was randomly selected and always had the same number of elements as the page size of mat1
. Here are the results, showing the ratio of the loop time versus the indexing time:
除了一些瞬态噪声外,还有一些清晰的图案。增加行数或列数(蓝线或红线)不会明显改变时间比例,时间比例徘徊在0.7到0.9之间,这意味着for循环的平均速度略快。增加页面数(黄线)意味着for循环必须迭代更多次,并且索引解决方案迅速开始胜出,当页面大小超过约150时,达到8倍的加速。
您是否
mat2 = nan(size(mat1))
在测试中进行了初始化?如果的第一个维度mat2
为1,事情将会更快,因为沿着该维度的其他元素将永远不会被使用。@CrisLuengo:是的,为了直接比较它们,我以与for循环解决方案中相同的方式对其进行了初始化。
for循环解决方案也将从较小的输出映像中受益。我认为这将产生重大变化,尤其是对于较大的数据。