MATLAB - 给定索引矩阵的矩阵列

时间:2015-05-30 09:28:36

标签: matlab matrix indexing

给定矩阵X,我想将每列的k个最小元素设置为零。对于向量x,我执行以下操作:

[~, ind] = sort(x)
x(ind(1:k)) = 0

现在,对于矩阵X,这不起作用:

[~, IND] = sort(X)
X(IND(1:k)) = 0

只需将第一列的k个最小元素设置为0.如何正确索引?

2 个答案:

答案 0 :(得分:3)

解决方案代码:使用sort的一种方法(获取按列排序的索引)&然后bsxfun(获得线性排序索引) -

%// Get 2D array of column-sorted indices for input X
[~,sorted_idx] = sort(X,1)

%// Get linear indices for the first k rows of sorted indices
lin_idx = bsxfun(@plus,sorted_idx(1:k,:),[0:size(X,2)-1]*size(X,1))

%// Use those indices to set them in X as zeros
X(lin_idx) = 0;

示例运行

1)输入:

X =
    61    67    86    54    49    40    13
    48    91    28    70    34    98    87
    79     7    27    86    71    58    52
    16    10    45    60    79     4     3
    56    36    49    50    31    48    87
k =
     3

2)排序索引:

>> [~,sorted_idx] = sort(X,1)
sorted_idx =
     2     3     2     1     1     1     1
     4     4     3     4     2     4     3
     5     5     4     5     5     5     4
     1     1     5     2     3     3     2
     3     2     1     3     4     2     5

3)仅从每列中选择前k个索引:

>> sorted_idx(1:k,:)
ans =
     4     3     3     5     5     4     4
     2     4     2     1     2     1     1
     5     5     4     4     1     5     3

4)我们需要将这些逐列索引转换为与2D数组X对应的线性索引。因此,遵循MATLAB中使用的列主索引,第一列保持原样,第二列必须添加number of rows in X的偏移量,第三列添加2*number of rows in X等等直到涵盖所有列。

以数学方式,我们会[0 5 10 15 20 25 30],即[0:6]*5,即将[0:size(X,2)-1]*size(X,1)作为一般情况添加到sorted_idx(1:k,:)。由于我们需要为sorted_idx(1:k,:)的每一行执行此操作,因此我们可以使用@plus自动扩展和求和(使用bsxfun)。请注意,这将以矢量化方式完成。因此,此处[0:size(X,2)-1]*size(X,1)的扩展将沿着行进行,然后使用sorted_idx(1:k,:)执行@plus的元素求和。所以,我们会有如此需要的线性指数 -

>> lin_idx = bsxfun(@plus,sorted_idx(1:k,:),[0:size(X,2)-1]*size(X,1))
lin_idx =
     4     8    13    20    25    29    34
     2     9    12    16    22    26    31
     5    10    14    19    21    30    33

5)最后,我们使用这些索引在X X(lin_idx) = 0中选择性地设置零。

答案 1 :(得分:1)

使用quantile(统计工具箱):

X = X .* bsxfun(@ge, X, quantile(X, k/size(X,1)));

工作原理

  1. quantile(X, k/size(X,1))为每列提供一个数字(分位数),使得该列中条目的分数k/size(X,1))小于该数字。这意味着,在每个列中,正好k个条目小于列分位数。
  2. 将每列与相应的分位数(bsxfun(@ge, ...))进行比较,得到的矩阵对于小于分位数的条目包含0,否则为1
  3. A的元素乘以2的结果使得A的所需值等于0
  4. 示例

    >> X = rand(5,3)
    X =
       0.088188645571510   0.907109055220371   0.805984932289666
       0.683710335821638   0.860456667336885   0.868488116302772
       0.120400876857723   0.338451384118250   0.669646599875533
       0.010699003144174   0.027158829325862   0.807778862315076
       0.557268230074914   0.800859355130033   0.897498282302820
    >> k=2;
    >> X = X.*bsxfun(@ge, X, quantile(X,k/size(X,1)))
    X =
                       0   0.907109055220371                   0
       0.683710335821638   0.860456667336885   0.868488116302772
       0.120400876857723                   0                   0
                       0                   0   0.807778862315076
       0.557268230074914   0.800859355130033   0.897498282302820