温馨提示:本文翻译自stackoverflow.com,查看原文请点击:matlab - Access different rows from multiple pages in 3D array
matlab multidimensional-array vectorization

matlab - 从3D数组中的多个页面访问不同的行

发布于 2020-03-27 11:04:47

如何在避免for-loop的同时访问3D数组中多个页面的不同行

假设我有一个10x5x3矩阵(mat1),我想将三个页面(例如第一,第二和第三页的第四,第二和第五行)中不同的单独行复制到另一个10x5x3矩阵的第一行mat2)。

我的解决方案使用for-loop。矢量化呢?

mat1 = randi(100, 10, 5, 3)
mat2 = nan(size(mat1))

rows_to_copy = [4, 2, 5]

for i = 1 : 3
    mat2(1, :, i) = mat1(rows_to_copy(i), :, i)
end

查看更多

查看更多

提问者
Andi
被浏览
133
gnovice 2019-07-03 23:34

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)).');


Timing

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倍的加速。