给定矩阵X,我想将每列的k个最小元素设置为零。对于向量x,我执行以下操作:
[~, ind] = sort(x)
x(ind(1:k)) = 0
现在,对于矩阵X,这不起作用:
[~, IND] = sort(X)
X(IND(1:k)) = 0
只需将第一列的k个最小元素设置为0.如何正确索引?
答案 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)));
工作原理:
quantile(X, k/size(X,1))
为每列提供一个数字(分位数),使得该列中条目的分数k/size(X,1))
小于该数字。这意味着,在每个列中,正好k
个条目小于列分位数。bsxfun(@ge, ...)
)进行比较,得到的矩阵对于小于分位数的条目包含0
,否则为1
。A
的元素乘以2的结果使得A
的所需值等于0
。示例强>:
>> 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