【问题标题】:Select entries from matrices according to indices in another matrix in MATLAB根据MATLAB中另一个矩阵中的索引从矩阵中选择条目
【发布时间】:2016-10-11 05:43:18
【问题描述】:

我有矩阵:

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,我得到了不同大小的矩阵。

添加I 是包含索引的m x (n+3),其他具有相应条目的(n+2) 矩阵是X,A1,A2,...,An,Y。当给定n 时,会生成A1,A2,...,An 矩阵。

有人可以帮我为这个任务编写 Matlab 代码吗?

【问题讨论】:

    标签: arrays matlab matrix


    【解决方案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));
    

    【讨论】:

    • 'varargin' 看起来如何像 @erfan?例如,您能否为给定的示例编写相应的“varargin”?谢谢
    • 看一下,我已经链接了matlab文档就可以了。它允许您将灵活数量的输入传递给您的函数。
    • 我根据您的矩阵包含了一个示例@user6951884
    • 谢谢@erfan。如果我在诸如{rand(s,r), rand(r,r,n), rand(r,s)} 的数组中生成这些a,b,c,...varargin 如何工作?这里rand(r,r,n) 表示n 数量r *r 矩阵(我不确定这是正确的编码方式)。因为我随机生成了这些带有可变参数的矩阵 ``n.
    • 如果在将矩阵传递给函数之前组合矩阵,则不再需要vararginrand 也不能以这种方式工作。如果您想以这种方式构建多个随机矩阵,则需要创建另一个函数。
    【解决方案2】:

    通常矩阵不会被解释为索引列表,但如果你使用 sub2ind,你可以拥有它。要使用它,您需要您正在处理的矩阵的大小。让我们以a开头的示例:

    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))]
    

    请记住,遵循该模式,您始终需要一个带有 (n_matrices + 1) 列的 I 矩阵。

    泛化

    让我们将这段代码推广到 n 个大小为 rxr 的中心矩阵和大小为 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)));
    

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

    【讨论】:

    • 这样你就不需要使用varargin,因为你手动将匿名函数应用于每个矩阵。这种手动工作权衡的目的是,通过这种方式,您可以避免使用循环(这在 MATLAB 中是更好的做法),您不需要单独的函数文件来在代码中使用它(如果您正在编写脚本而不是函数),它只有两行。
    • 谢谢@Carmine。如果我在{rand(s,r), rand(r,r,n), rand(r,s)} 等数组中生成这些a,b,c,...,这将如何工作?这里rand(r,r,n) 表示nr *r 矩阵的数量(我不确定这是正确的编码方式)。我什至不知道如何将这样的数组传递给varargin
    • 据我了解,在您的代码中,我需要手动编写output。但是,如果我知道第一个和最后一个矩阵,则不。中心矩阵的个数取决于参数n,那么可能很难为每个noutput
    • 我也很担心。
    • OP 我不确定我是否完全理解您在描述中添加的文字@Frey 我在答案中添加了概括
    猜你喜欢
    • 1970-01-01
    • 2015-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多