MATLAB-给定索引矩阵的矩阵的置换列
给定一个矩阵X,我想将每列的k个最小元素设置为零。对于向量x,我执行以下操作:MATLAB-给定索引矩阵的矩阵的置换列,matlab,matrix,indexing,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。如何正确编制索引?解决方案代码:一种方法(获取按列排序的索引)然后(获取线性排序的索引)- 样本运行 1) 投入: 2) 分类索引: >> [~,sorted_idx] = sort(X,1) so
[~, ind] = sort(x)
x(ind(1:k)) = 0
现在,对于矩阵X,这不起作用:
[~, IND] = sort(X)
X(IND(1:k)) = 0
只需将第一列的k最小元素设置为0。如何正确编制索引?解决方案代码:一种方法(获取按列排序的索引)然后(获取线性排序的索引)- 样本运行 1) 投入: 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中使用的列主索引之后,第一列保持原样,第二列必须添加X中行数的偏移量,第三列将添加2*X
中的行数,依此类推,直到所有列都被覆盖
从数学上讲,我们将有[0510152530]
,即[0:6]*5
,即作为一个一般情况[0:size(X,2)-1]*size(X,1)
,添加到排序的idx(1:k,:)
。由于我们需要对排序的每一行进行此操作_idx(1:k,:)
,因此我们可以使用bsxfun
自动展开和求和(使用@plus
)。请注意,这将以矢量化方式完成。因此,这里沿行进行[0:size(X,2)-1]*size(X,1)
的扩展,然后使用@plus
执行元素级的求和,排序为\u idx(1:k,:)
。这样,我们就有了非常需要的线性指数-
>> 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
使用(统计工具箱):
它的工作原理:
>> 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
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
如果你有时间,你能解释一下bsxfun到底做什么吗?“这样一个优雅的解决方案将大大改进这个答案。”BananaCode在其中添加了一些解释。这个答案看起来非常有趣。准确地解释它是如何工作的将大大有助于它的实用性。
X = X .* bsxfun(@ge, X, quantile(X, k/size(X,1)));
>> 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