【问题标题】:Keep n largest values per column and set the rest to zero in MATLAB without a loop在没有循环的情况下在 MATLAB 中保留每列 n 个最大值并将其余值设置为零
【发布时间】:2015-10-19 11:12:35
【问题描述】:

我有一个未排序的数字矩阵,我想保留每列的 n 个最大(不一定是唯一的)值,并将其余的值设置为零。

我想出了如何用循环来做到这一点:

a = [4 8 12 5; 9 2 6 18; 11 3 9 7; 8 9 12 4]
k = 2

for  n = 1:4
    [y, ind] = sort(a(:,n), 'descend');
    a(ind(k+1:end),n) = 0;
end
a

这给了我: 一个=

 4     8    12     5
 9     2     6    18
11     3     9     7
 8     9    12     4

k =

 2

一个=

 0     8    12     0
 9     0     0    18
11     0     0     7
 0     9    12     0

但是,当我尝试消除循环时,我似乎无法正确建立索引,因为:

a = [4 8 12 5; 9 2 6 18; 11 3 9 7; 8 9 12 4]
k = 2

[y, ind] = sort(a, 'descend');
b = ind(k+1:end,:)
a(b) = 0

这给了我这个:(这不是我想做的) 一个=

 4     8    12     5
 9     2     6    18
11     3     9     7
 8     9    12     4

k =

 2

b =

 4     3     3     1
 1     2     2     4

一个=

 0     8    12     5
 0     2     6    18
 0     3     9     7
 0     9    12     4

我索引错了吗?我必须使用循环吗?

我在开始时参考了这个问题,但这并不是我想要做的:How to find n largest elements in an array and make the other elements zero in matlab?

【问题讨论】:

    标签: arrays matlab sorting indexing vectorization


    【解决方案1】:

    这是一个使用bsxfun -

    %// Get descending sorting indices per column
    [~, ind] = sort(a,1, 'descend')
    
    %// Get linear indices that are to be set to zeros and set those in a to 0s
    rem_ind = bsxfun(@plus,ind(n+1:end,:),[0:size(a,2)-1]*size(a,1))
    a(rem_ind) = 0
    

    示例运行 -

    a =
         4     8    12     5
         9     2     6    18
        11     3     9     7
         8     9    12     4
    n =
         2
    ind =
         3     4     1     2
         2     1     4     3
         4     3     3     1
         1     2     2     4
    rem_ind =
         4     7    11    13
         1     6    10    16
    a =
         0     8    12     0
         9     0     0    18
        11     0     0     7
         0     9    12     0
    

    【讨论】:

      【解决方案2】:

      你很亲密。 sort 函数中的 ind 为您提供了该特定值将出现在排序输出中的每一列的行位置。如果要正确索引到矩阵并消除条目,则需要做一些额外的工作。您知道对于I 的每一列,这告诉您我们需要从该特定列中删除这些条目。因此,我要做的是使用I 的每一列生成列主要线性索引,作为我们需要消除的行。

      尝试这样做:

      a = [4 8 12 5; 9 2 6 18; 11 3 9 7; 8 9 12 4];
      k = 2;
      [y, ind] = sort(a, 'descend');
      
      %// Change here
      b = sub2ind(size(a), ind(k+1:end,:), repmat(1:size(a,2), size(a,1)-k, 1));
      a(b) = 0;
      

      我们使用sub2ind 帮助我们生成列主索引,其中行由kth 元素之后的ind 中的值表示,我们需要的列是该矩阵中的每一列。在排序后截断k 值后剩余size(a,1)-k 行,因此我们生成的列值从1 到a 中的列数和剩余行数一样多。

      我们得到这个输出:

      >> a
      
      a =
      
           0     8    12     0
           9     0     0    18
          11     0     0     7
           0     9    12     0
      

      【讨论】:

      • ind 和 I 应该是同一个变量吗?
      • @ErinGoBragh - 不用担心。让我知道这是否适合你!
      • 成功了!谢谢,我只是想不通最后一点索引。
      • @ErinGoBragh - 我很高兴 :) 是的,我不得不花几分钟时间在 MATLAB 上摆弄,直到我做对了。相信我,我第一次尝试也没有成功!
      • 以为你给我留了一个 bsxfun ! ;) 好吧,我的解决方案开始时与您的相同。
      猜你喜欢
      • 2021-12-20
      • 2023-01-24
      • 2017-03-01
      • 1970-01-01
      • 2021-03-03
      • 2020-11-27
      • 2020-06-21
      • 2011-07-01
      • 2015-12-02
      相关资源
      最近更新 更多