根据索引将多维数组中的数据提取为2个dims

时间:2016-01-28 15:31:33

标签: matlab indexing

我有一个巨大的(1000000x100x7)矩阵,我需要根据索引向量(100x1)创建一个(1000000x100x1)矩阵,每个位置保存1 2 3 4 5 6或7。

我不想使用循环

1 个答案:

答案 0 :(得分:3)

问题(我认为)

首先,让我尝试创建一个最小的工作示例,我认为它可以捕获您想要做的事情。您有一个矩阵A和一个索引向量index

A = rand(1000000, 100, 7);
index = randi(7, [100, 1]);

你想做这样的事情:

[I,J,K] = size(A);
B = zeros(I,J);
for i=1:I
    for j=1:J
        B(i,j) = A(i,j,index(j));
    end
end

只有你在没有循环的情况下这样做。

线性索引

实现此目的的一种方法是使用线性索引。这有点棘手,取决于矩阵在内存中的排列方式,我会解释它的工作非常糟糕,但您也可以查看sub2ind和{的文档。 {1}}函数。

无论如何,这意味着如果您的(1,000,000 x 100 x 7)矩阵以列主格式存储,您可以用许多不同的方式引用相同的元素,即:

ind2sub

都是指矩阵的相同元素。无论如何,妙语是:

A(i, j, k)
A(i, j + 100*(k-1))
A(i + 1000000*(j-1 + 100*(k-1)))

当然,我们应该验证这会产生相同的答案:

linear_index = (1:J)' + J*(index-1);
B_noloop = A(:, linear_index);

耶!

性能与可读性

因此,在我的计算机上进行测试,嵌套循环耗时5.37秒,无循环版本耗时0.29秒。但是,很难说出该代码中发生了什么。也许更合理的妥协是:

>> isequal(B, B_noloop)
ans =
     1

它会对矩阵的最长维度进行矢量化,从而获得大部分(0.43秒),但保持原始代码的可读性。