【问题标题】:How to create a k matrix according to an array of indices using matlab?如何使用matlab根据索引数组创建k矩阵?
【发布时间】:2017-05-14 19:03:04
【问题描述】:

我需要在 MatLab 中创建具有不同行数的 k 矩阵。我该怎么做?

假设我有k=52 矩阵,就像那个矩阵一样(矩阵Mpop 可以看作任何矩阵)

Mpop = 
    0.9284    0.9299  -46.3239    1.2597   15.1842   21.8344   68.1583
   -0.9948   -2.0102  -44.9439    1.7241   15.7423   38.2638   83.2077
    1.1801   -0.9930  -41.8621    3.5203   14.3528   92.4522  134.3142
    0.8557   -0.8754  -41.7513    2.7033   13.9570   67.2608  109.0121
    1.1149    1.9312  -41.6132    2.6042   14.7964   66.1055  107.7187
    1.1153    0.1656  -41.2766    4.4585   13.8216  120.1216  161.3983
   -1.1358   -1.9447  -40.9061    1.9565   14.6642   47.1186   88.0247
    0.0062   -0.2411  -40.4918    1.5405   13.8066   33.3358   73.8276
   -0.1984   -1.1021  -39.9417    1.2500   13.6128   24.7840   64.7256
    0.0876   -0.2284  -39.8141    2.2970   13.4819   56.0590   95.8732

和(IDX 是一个向量,其值为1k

IDX = 
     3
     4
     1
     3
     2
     3
     4
     5
     3
     4

所以,如果IDX 的行i 等于1,我需要将Mpop 的行i 放入矩阵Mpop1 中,以同样的方式,如果行i IDX 等于2,我需要将Mpopi 行放入矩阵Mpop2 等中。

我可以这样做

Mpop1 = zeros(10,7);
Mpop2 = zeros(10,7);
Mpop3 = zeros(10,7);
Mpop4 = zeros(10,7);
Mpop5 = zeros(10,7);

    for i=1:npop
        if IDX(i,1)==1
            Mpop1(i,:) = Mpop(i,:)
        elseif IDX(i)==2
            Mpop2(i,:) = Mpop(i,:)
        elseif IDX(i)==3
            Mpop3(i,:) = Mpop(i,:)
        elseif IDX(i)==4
            Mpop4(i,:) = Mpop(i,:)
        else IDX(i)==5
            Mpop5(i,:) = Mpop(i,:)
        end
    end
Mpop1 = Mpop1(all(Mpop1,2),:)
Mpop2 = Mpop2(all(Mpop2,2),:)
Mpop3 = Mpop3(all(Mpop3,2),:)
Mpop4 = Mpop4(all(Mpop4,2),:)
Mpop5 = Mpop5(all(Mpop5,2),:)

但这并不好,因为K 可能与5 不同。

那么,如果我有 K 的任何值,我该怎么做?

【问题讨论】:

    标签: matlab for-loop matrix


    【解决方案1】:

    创建这 5 个矩阵是个坏主意。而是使用单元格数组并使用其索引来访问/使用特定矩阵。这是使用 2 个循环的解决方案:

    numIDX = numel(IDX);            %Number of elements of IDX
    
    tmp = cell(k,numIDX);           %Pre-allocation
    for ii=1:numIDX
        tmp{IDX(ii),ii}=Mpop(ii,:); %Converted the if-else conditions into a single line
    end
    
    req = cell(k,1);                %Pre-allocation of the required cell
    for jj=1:k
       req{jj}=vertcat(tmp{jj,:});  %vertically concatenating/ removing the empty cells of tmp
    end
    

    现在使用此元胞数组的索引来访问Mpop1Mpop2Mpop3Mpop4Mpop5,即使用req{1}req{2}req{3}req{4}req{5}

    【讨论】:

    【解决方案2】:

    如果您的矩阵有不同的名称,那么您就无法通过这种方式进行其他操作。然而,实现这一点的一个好方法可能是使用元胞数组(有关它们,请参阅this StackOverflow answer)。基本上,您的所有矩阵都将位于一个变量中,您可以选择具有索引的正确矩阵,在您的情况下为 IDX(i)

    【讨论】:

      【解决方案3】:

      作为stated by Sardar Usama,最好使用元胞数组而不是创建动态变量。

      这是另一种创建无循环元胞数组的方法,使用 accumarray 函数:

      result = accumarray(IDX, (1:numel(IDX)).', [], @(x){Mpop(sort(x),:)})
      

      这会根据IDX 中的值将整数从1 拆分为numel(IDX) 的组;将这些索引应用到原始矩阵Mpop;并将生成的子矩阵打包到一个元胞数组中。

      【讨论】:

      • 在这种情况下我将如何访问Mpop1Mpop2 等?
      • @ElcioSilveira 就像我的回答一样。 result{1}, result{2}, ...
      【解决方案4】:

      正如 juef 所建议的,使用元胞数组是可行的方法:

      % define the length of the arrays/matrices
      nID = max(IDX);
      npop = length(IDX);
      
      % allocate memory
      Mpops = cell(nID, 1);
      [Mpops{:}] = deal(zeros(10,7));
      
      % fill the matrices
      for i=1:npop
          Mpops{IDX(i)}(i, :) = Mpop(i,:);
      end
      
      % remove empty rows
      for i=1:nID
          Mpops{i} = Mpops{i}(all(Mpops{i},2),:);
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-10
        • 2015-05-29
        • 2017-03-19
        • 1970-01-01
        相关资源
        最近更新 更多