【问题标题】:Removing zeros and then vertically collapse the matrix删除零,然后垂直折叠矩阵
【发布时间】:2015-02-23 19:15:11
【问题描述】:

在 MATLAB 中,假设我有一组方阵,例如 A,trace(A)=0 如下:

例如,

A = [0 1 2; 3 0 4; 5 6 0] 

如何删除零,然后垂直折叠矩阵,如下所示:

A_reduced = [1 2; 3 4; 5 6]

更一般地说,如果零可以出现在列中的任何位置(即,不一定在长对角线上)怎么办?当然,假设所有列的零总数相同。

矩阵可以很大(数百 x 数百维)。因此,将赞赏一种有效的方法。

【问题讨论】:

  • 以前试过这个。这不维护矩阵结构 - 我指的是“垂直折叠矩阵”部分。
  • 对不起。当我在原始帖子中使用 A' 时,我想我让你们很多人感到困惑。我的意思是表示改变/减少的A,而不是转置的A。我现在已将 A' 更改为 A_reduced。
  • 不应该每行中的零数量相同,而不是问题中所述的每列中的零数量相同,以启用垂直折叠?像这样 - A = [0 3 0 2; 3 0 0 1; 7 0 6 0; 1 0 6 0;0 16 0 9]?
  • 您能否使用具有"total number of zeros for all columns are the same" 条件的更随机样本并说明所需的输出?例如,像这样的东西每列都有两个零 - A = [0 3 7 1 0;3 0 0 0 6; 0 0 6 5 0;3 2 0 0 6],那么这种情况下的预期输出必须是什么?
  • 您的示例A_reduced 假设所有行 中的零数相同,然后您可以水平压缩。所以你的问题令人困惑。无论如何,我认为我的回答转换了两种可能性

标签: arrays matlab matrix


【解决方案1】:
  • 垂直压缩矩阵(假设每一列都有相同数量的零):

    A_reduced_v = reshape(nonzeros(A), nnz(A(:,1)), []);
    
  • 水平压缩矩阵(假设每一行都有相同数量的零):

    A_reduced_h = reshape(nonzeros(A.'), nnz(A(1,:)), []).';
    

【讨论】:

    【解决方案2】:

    案例#1

    假设A在所有行中具有相同数量的零,您可以使用它水平(即每行)压缩它 -

    At = A' %//'# transpose input array
    out = reshape(At(At~=0),size(A,2)-sum(A(1,:)==0),[]).' %//'# final output
    

    示例代码运行 -

    >> A
    A =
         0     3     0     2
         3     0     0     1
         7     0     6     0
         1     0     6     0
         0    16     0     9
    >> out
    out =
         3     2
         3     1
         7     6
         1     6
        16     9
    

    案例#2

    如果A 在所有列 中具有相同数量的零,您可以使用类似这样的方式垂直(即每列)压缩它 -

    out = reshape(A(A~=0),size(A,1)-sum(A(:,1)==0),[])  %//'# final output
    

    示例代码运行 -

    >> A
    A =
         0     3     7     1     0
         3     0     0     0    16
         0     0     6     6     0
         2     1     0     0     9
    >> out
    out =
         3     3     7     1    16
         2     1     6     6     9
    

    【讨论】:

    • 现在我明白你的答案 :-) 这个问题混合了两种解释,不是吗?
    • 没错!我最近的一个烦恼(由这个网站引起)是人们如何错误地选择他们的例子:-)
    • @LuisMendo 另一个是当我建议使用矢量化方法并且 OP 回来时 - “哦,内存快用完了!因为我正在使用 1000 亿个数据点!”。我的意思是来吧,必须在一开始就说明! :)
    • @LuisMendo 哈哈,讨论!!好吧,是的,我想我们也在SO 上磨练我们的“心理主义者”技能!!关于通灵师徽章.. 嗯SO 必须了解我们的想法,了解何时授予这些徽章:)
    • 好的,就是这样。我要写一篇 Meta 帖子大声笑。今晚晚些时候再写。
    【解决方案3】:

    这似乎有效,通过转置来获得正确的行为非常繁琐:

    >> B = A';
    >> C = B(:);
    >> reshape(C(~C==0), size(A) - [1, 0])'
    
    ans =
    
         1     2
         3     4
         5     6
    

    【讨论】:

    • 这个解决方案对我有用(有和没有转置)。谢谢。
    【解决方案4】:

    由于您的零点始终位于主对角线上,您可以执行以下操作:

    l = tril(A, -1);
    u = triu(A,  1);
    out = l(:, 1:end-1) + u(:, 2:end)
    

    【讨论】:

      【解决方案5】:

      一个正确且非常简单的方法是:

      A = [0 1 2; 3 0 4; 5 6 0]
      
      A =
      
       0     1     2
       3     0     4
       5     6     0
      
      A = sort((A(find(A))))
      
      A =
      
       1
       2
       3
       4
       5
       6
      
      A = reshape(A, 2, 3)
      
      A =
      
       1     3     5
       2     4     6
      

      【讨论】:

        【解决方案6】:

        我想出了与 E 先生几乎相同的解决方案,但使用了另一个 reshape 命令。这个解决方案更通用,因为它使用A 中的行数来创建最终矩阵,而不是计算零的数量或假设零的固定数量..

        B = A.';
        B = B(:);
        C = reshape(B(B~=0),[],size(A,1)).'
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-11-13
          • 1970-01-01
          • 2017-03-23
          • 1970-01-01
          • 2019-10-10
          • 2020-03-11
          • 2015-12-10
          相关资源
          最近更新 更多