使用向量索引没有线性索引的矩阵 [英] Use a vector to index a matrix without linear index

查看:156
本文介绍了使用向量索引没有线性索引的矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

G'day,
我正试图找到一种方法,使用[x,y]点矢量从MATLAB中的大矩阵中索引。
通常,我会将下标点转换为矩阵的线性索引。(例如。使用向量作为矩阵的索引)然而,矩阵是4维的,我想要采用第3和第3的所有元素具有相同的第一和第二维度的第四维度。让我希望用一个例子来证明:

G'day, I'm trying to find a way to use a vector of [x,y] points to index from a large matrix in MATLAB. Usually, I would convert the subscript points to the linear index of the matrix.(for eg. Use a vector as an index to a matrix) However, the matrix is 4-dimensional, and I want to take all of the elements of the 3rd and 4th dimensions that have the same 1st and 2nd dimension. Let me hopefully demonstrate with an example:

Matrix = nan(4,4,2,2); % where the dimensions are (x,y,depth,time)
Matrix(1,2,:,:) = 999; % note that this value could change in depth (3rd dim) and time (4th time) 
Matrix(3,4,:,:) = 888; % note that this value could change in depth (3rd dim) and time (4th time) 
Matrix(4,4,:,:) = 124;

现在,我希望能够使用下标(1,2)和(3, 4)等不仅返回 Matrix(:,:,1,1)中存在的999和888,而且还存在于中的内容矩阵(:,:,1,2)矩阵(:,:,2,1)矩阵( :,:,2,2),依此类推(IRL, Matrix 的尺寸可能更像是尺寸(矩阵)=(300 250 30 200)

Now, I want to be able to index with the subscripts (1,2) and (3,4), etc and return not only the 999 and 888 which exist in Matrix(:,:,1,1) but the contents which exist at Matrix(:,:,1,2),Matrix(:,:,2,1) and Matrix(:,:,2,2), and so on (IRL, the dimensions of Matrix might be more like size(Matrix) = (300 250 30 200)

我不想使用线性索引,因为我希望结果在类似的矢量时尚。例如,我想得到的结果如下:

I don't want to use linear indices because I would like the results to be in a similar vector fashion. For example, I would like a result which is something like:

ans(time=1)
999 888 124
999 888 124
ans(time=2)
etc etc etc
etc etc etc

我还想补充一点,由于我正在处理的矩阵的大小,速度是一个问题 - 这就是为什么我要使用用于索引数据的下标索引。

I'd also like to add that due to the size of the matrix I'm dealing with, speed is an issue here - thus why I'd like to use subscript indices to index to the data.

我还应该提一下(与此不同) estion:使用下标访问值而不使用sub2ind )因为我想要存储在i和jth索引的额外维度3和4中的所有信息,我不认为 sub2ind 的稍微快一点的版本仍然会不要削减它..

I should also mention that (unlike this question: Accessing values using subscripts without using sub2ind) since I want all the information stored in the extra dimensions, 3 and 4, of the i and jth indices, I don't think that a slightly faster version of sub2ind still would not cut it..

推荐答案

我可以想到三种方法来解决这个问题

I can think of three ways to go about this

只需循环遍历所有2D索引,并使用冒号访问剩余维度:

Just loop over all the 2D indices you have, and use colons to access the remaining dimensions:

for jj = 1:size(twoDinds,1)
    M(twoDinds(jj,1),twoDinds(jj,2),:,:) = rand;
end



线性指数的矢量化计算



跳过 sub2ind 并向量化线性指数的计算:

Vectorized calculation of Linear indices

Skip sub2ind and vectorize the computation of linear indices:

% generalized for arbitrary dimensions of M

sz = size(M);
nd = ndims(M);

arg = arrayfun(@(x)1:x, sz(3:nd), 'UniformOutput', false);

[argout{1:nd-2}] = ndgrid(arg{:});

argout = cellfun(...
    @(x) repmat(x(:), size(twoDinds,1),1), ...
    argout, 'Uniformoutput', false);

twoDinds = kron(twoDinds, ones(prod(sz(3:nd)),1));

% the linear indices
inds = twoDinds(:,1) + ([twoDinds(:,2) [argout{:}]]-1) * cumprod(sz(1:3)).';



Sub2ind



只需使用就绪 - 随Matlab一起提供的工具:

Sub2ind

Just use the ready-made tool that ships with Matlab:

inds = sub2ind(size(M), twoDinds(:,1), twoDinds(:,2), argout{:});



速度



那么哪一个是最快的?让我们找出:

Speed

So which one's the fastest? Let's find out:

clc

M = nan(4,4,2,2);

sz = size(M);
nd = ndims(M);

twoDinds = [...
    1 2
    4 3
    3 4
    4 4
    2 1];

tic
for ii = 1:1e3
    for jj = 1:size(twoDinds,1)
        M(twoDinds(jj,1),twoDinds(jj,2),:,:) = rand;
    end
end
toc


tic
twoDinds_prev = twoDinds;
for ii = 1:1e3

    twoDinds = twoDinds_prev;

    arg = arrayfun(@(x)1:x, sz(3:nd), 'UniformOutput', false);

    [argout{1:nd-2}] = ndgrid(arg{:});

    argout = cellfun(...
        @(x) repmat(x(:), size(twoDinds,1),1), ...
        argout, 'Uniformoutput', false);

    twoDinds = kron(twoDinds, ones(prod(sz(3:nd)),1));
    inds = twoDinds(:,1) + ([twoDinds(:,2) [argout{:}]]-1) * cumprod(sz(1:3)).';

    M(inds) = rand;

end
toc


tic
for ii = 1:1e3

  twoDinds = twoDinds_prev;

    arg = arrayfun(@(x)1:x, sz(3:nd), 'UniformOutput', false);

    [argout{1:nd-2}] = ndgrid(arg{:});

    argout = cellfun(...
        @(x) repmat(x(:), size(twoDinds,1),1), ...
        argout, 'Uniformoutput', false);

    twoDinds = kron(twoDinds, ones(prod(sz(3:nd)),1));

    inds = sub2ind(size(M), twoDinds(:,1), twoDinds(:,2), argout{:});

    M(inds) = rand;
end
toc

结果:

Elapsed time is 0.004778 seconds.  % loop
Elapsed time is 0.807236 seconds.  % vectorized linear inds
Elapsed time is 0.839970 seconds.  % linear inds with sub2ind

结论:使用循环。

当然,上面的测试很大程度上受到JIT无法编译最后两个循环的影响,以及对4D阵列的非特异性(后两种方法也适用于ND)阵列)。为4D制作专用版本无疑会更快。

Granted, the tests above are largely influenced by JIT's failure to compile the two last loops, and the non-specificity to 4D arrays (the last two method also work on ND arrays). Making a specialized version for 4D will undoubtedly be much faster.

然而,由于JIT,使用简单循环的索引最简单,最简单,也很快。

Nevertheless, the indexing with simple loop is, well, simplest to do, easiest on the eyes and very fast too, thanks to JIT.

这篇关于使用向量索引没有线性索引的矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆