3D矩阵:如何在MATLAB中将(行,列)对与3维通配符一起使用?
我有一个3维矩阵,以及(行,列)对的列表.我想提取二维矩阵,该二维矩阵对应于那些位置的元素,并通过矩阵的深度进行投影.例如,假设
I have a 3 dimensional matrix, and a list of (row, column) pairs. I would like to extract the 2 dimensional matrix that corresponds to the elements in those positions, projected through the depth of the matrix. For instance, suppose,
>> a = rand(4, 3, 2)
a(:,:,1) =
0.5234 0.7057 0.0282
0.6173 0.2980 0.9041
0.7337 0.9380 0.9639
0.0591 0.8765 0.1693
a(:,:,2) =
0.8803 0.2094 0.5841
0.7151 0.9174 0.6203
0.7914 0.7674 0.6194
0.2009 0.2542 0.3600
>> rows = [1 4 2 1];
>> cols = [1 2 1 3];
我想得到的是
0.5234 0.8765 0.6173 0.0282
0.8803 0.2542 0.7151 0.5841
也许具有一些尺寸上的排列.另外,尽管此示例在最后一维中使用通配符,但在某些情况下,也存在通配符在第一或第二维中的情况.
maybe with some permutation of dimensions. Also, although this example has the wildcard in the last dimension, I also have cases where it's in the first or second.
我天真地尝试了a(rows, cols, :)
,并得到了一个3d矩阵,其中对角平面就是我想要的.我还发现了sub2ind
,它将从a(:,:,1)
平面中提取所需的元素.我可以使用其中之一来实现自己想要的功能,但我想知道是否还有我遗漏的更规范,更优雅或更有效的方法?
I naively tried a(rows, cols, :)
and got a 3d matrix where the diagonal plane is what I want. I also found sub2ind
, which will extract the desired elements from the a(:,:,1)
plane. I could work with one of these to get to what I want, but I'm wondering is there a more canonical, elegant, or efficient method that I'm missing?
根据下面发布的答案,这是我使用的解决方案,
This was the solution I used, based on the answer posted below,
sz = size(a);
subs = [repmat(rows, [1, sz(3)]);
repmat(cols, [1, sz(3)]);
repelem([1:sz(3)], length(rows))];
result = a(sub2ind(sz, subs(1,:), subs(2,:), subs(3,:)));
sub2ind
几乎是您在此处用于将下标转换为线性索引的方法(除了自己手动计算线性索引之外).您可以执行以下操作,将rows
和cols
转换为线性索引(在2D切片中),然后向这些索引添加偏移量(等于2D切片中的元素数),以对三维中的所有元素进行采样.
sub2ind
is pretty much what you have to use here to convert your subscripts into linear indices (apart from manually computing the linear indices yourself). You can do something like the following which will convert the rows
and cols
to a linear index (in a 2D slice) and then it adds an offset (equal to the number of elements in a 2D slice) to these indices to sample all elements in the third dimension.
sz = size(a);
inds = sub2ind(sz(1:2), rows, cols);
inds = bsxfun(@plus, inds, (0:(sz(3)-1)).' * prod(sz(1:2)));
result = a(inds);
并自己实际计算线性指数
And to actually compute the linear indices yourself
inds = (cols - 1) * sz(1) + rows;
inds = bsxfun(@plus, inds, (0:(sz(3) - 1)).' * prod(sz(1:2)));
result = a(inds);
另一种选择是对初始矩阵进行置换,以将第三维变为第一维,将其重塑为2D矩阵,然后将线性索引用作第二个下标
Another option would be to permute your initial matrix to bring the third dimension to the first dimension, reshape it to a 2D matrix, and then use the linear index as the second subscript
% Create a new temporary matrix
anew = reshape(permute(a, [3, 1, 2]), size(a, 3), []);
% Grab all rows (the 3rd dimension) and compute the columns to grab
result = anew(:, (cols - 1) * size(a, 1) + rows);