根据MATLAB中另一个矩阵中的索引从矩阵中选择条目

时间:2016-10-11 05:43:19

标签: arrays matlab matrix

我有矩阵:

a=  0.8147    0.1270    0.6324
    0.9058    0.9134    0.0975

b=  0.2785    0.9649    0.9572
    0.5469    0.1576    0.4854
    0.9575    0.9706    0.8003

c = 0.1419    0.7922
    0.4218    0.9595
    0.9157    0.6557

我还有另一个矩阵

   I=  1 3 1 1
       2 1 3 2

我希望得到d矩阵

d= a(1,3) b(3,1) c(1,1)
   a(2,1) b(1,3) c(3,2)

其中索引是I矩阵的两个连续条目 这是我得到的一个例子。但是,我为a,b,c,..I获得了不同的大小矩阵。

已添加Im x (n+3),其中包含索引,其他(n+2)矩阵的相应条目为X,A1,A2,...,An,Y。提供n后,会生成A1,A2,...,An个矩阵。

有人可以帮我写一下这个任务的Matlab代码吗?

2 个答案:

答案 0 :(得分:1)

通常,矩阵不会被解释为索引列表,但如果使用sub2ind,则可以使用此矩阵。要使用它,您需要要处理的矩阵的大小。让我们以一个例子开头:

a(sub2ind(size(a), I(:,1), I(:,2)))

如果您首先将新生成的矩阵分配给变量名,则代码不会更改。

将使用列I(:,1)作为行,I(:,2)作为列。

为了使代码更具可读性,您可以定义执行此操作的匿名函数,让我们将其称为idx:

idx = @(m,I,i)(sub2ind(size(m), I(:,i), I(:,i+1)))

所以最后代码将是

d = [a(idx(a,I,1)), b(idx(b,I,2)), c(idx(c,I,3))]

如果您首先将新生成的矩阵分配给变量名,则代码不会更改。

其他详情

让我们以2个中心矩阵为例:

a = rand(3,1)   % 3 rows, 1 column
b = rand(3,3)   % 3 rows, 3 columns
c = rand(3,3)   % another squared matrix
d = rand(3,1)   % 3 rows, 1 column

匿名函数的定义是相同的,您只需更改输出向量的定义:

output = [a(idx(a,I,1)), b(idx(b,I,2)), c(idx(c,I,3)), d(idx(d,I,3))]

请注意,遵循该模式,您始终需要一个I矩阵,其中包含(n_matrices + 1)列。

概括

让我们将这个代码推广到n个大小为rxr的中心矩阵和#34; side matrices"大小为rxc。我将在这个例子中使用这些参数的一些值,但你可以使用你想要的。

让我生成一个使用示例:

r = 3;
c = 4;
n = 3;

a = rand(r,c);   % 2D array
b = rand(r,r,n); % 3D array, along z = 1:n you have 2D matrices of size rxr
c = rand(r,c); 

I =  [1 3 1 2 1 3; 2 1 3 1 1 1];

我编写的代码很容易使用cat扩展来追加矩阵(注意函数中的2告诉MATLAB追加列的方向)和for循环:

idx = @(m,I,i)(sub2ind(size(m), I(:,i), I(:,i+1)))

d = a(idx(a,I,1));
for i = 1:n
    temp = b(:,:,i);
    d = cat(2,d,temp(idx(tmp,I,i+1)));
end
d = cat(2,d,c(idx(c,I,n+1)));

如果你真的不想解决任何问题"手动",你可以使用单元格数组将所有矩阵放在一起,然后循环地将匿名函数应用于单元格数组中的每个矩阵。

答案 1 :(得分:1)

您可以使用varargin执行此操作。假设你的矩阵是按照你想要的方式构建你想要的输出(根据Carmine's answer更新):

function out = IDcombiner(I, varargin)
out = zeros(size(I, 1), nargin-1);
idx = @(m, I, ii) (sub2ind(size(m), I(:, ii), I(:, ii+1)));
for ii = 1:1:nargin-1
    out(:, ii) = varargin{ii}(idx(varargin{ii}, I, ii));
end

现在使用此功能,您可以在灵活的输入数量上进行选择:

out = IDcombiner(I, a, b, c)

out =

    0.6324    0.9575    0.1419
    0.9058    0.9572    0.6557

还有一个单行解决方案,我不推荐,因为它大大降低了代码的可读性,并没有帮助你获得更多收益:

IDcombiner = @(I,varargin) ...
    cell2mat(arrayfun(@(x) varargin{x}(sub2ind(size(varargin{x}), ...
    I(:,x), I(:,x+1))), 1:nargin-1, 'UniformOutput', false));