matlab multidimensional-array vectorization

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

``````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

132 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: 