为了深入了解上面的标题,我有一个定义如下的向量:
A = [1 1 1 1 1 2 2 2 3 3 3 4 4 4];
Run Code Online (Sandbox Code Playgroud)
鉴于上述向量,如何在MATLAB中创建此矩阵?
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 2 2 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 3 3 3 3 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 4 4 4
Run Code Online (Sandbox Code Playgroud)
基本上,对于每个唯一值A,有一行与之关联.对于每一行,等于感兴趣的特定值的位置被放置在它们各自的列中.
在MATLAB中执行此操作的最有效方法是什么?
另一种方法是通过bsxfun和unique.假设这A是一个行向量,您将执行以下操作:
un = unique(A.', 'stable');
out = bsxfun(@times, bsxfun(@eq, A, un), un);
Run Code Online (Sandbox Code Playgroud)
out包含您想要的结果.这段代码值得一些解释.第一行代码确定A存储在中的所有唯一条目un,但按stable顺序或按照它们遇到的顺序提供它们.不这样做也会对值进行排序.我认为从1到4的值的情况是一个简化的例子,你想要以任意顺序对数字执行此操作,并且它们也出现在向量中的任何位置.
第二行代码实际上非常优雅.让我们从第一个bsxfun嵌套在里面的调用开始:
bsxfun(@eq, A, un)
Run Code Online (Sandbox Code Playgroud)
bsxfun是一个非常好的功能,广播单身尺寸.这对我们的情况来说意味着它A是一个行向量并且un是一个列向量,这将产生一个矩阵,我们在其中找到两个矩阵的元素相等 - 一个矩阵A与我们所拥有的元素一样复制行向量in un和另一个矩阵,它复制了列矢量中的元素数量A.结果是一个矩阵,其中每一行告诉您从(第一行)的开头到(最后一行)的开头从哪个位置A匹配特定值.最后一部分是采用这个相等矩阵,并使用另一个调用进行逐元素乘法,这样就可以像在里面那样以列为单位再次进行广播.结果是将每行的确切位置归零,这些位置不等于表示的相应值,因此我们得到了结果.ununununbsxfununbsxfun(@eq, A, un)un
>> A = [1 1 1 1 1 2 2 2 3 3 3 4 4 4]
A =
Columns 1 through 13
1 1 1 1 1 2 2 2 3 3 3 4 4
Column 14
4
Run Code Online (Sandbox Code Playgroud)
调用上面的代码给我们:
>> out
out =
Columns 1 through 13
1 1 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 2 2 2 0 0 0 0 0
0 0 0 0 0 0 0 0 3 3 3 0 0
0 0 0 0 0 0 0 0 0 0 0 4 4
Column 14
0
0
0
4
Run Code Online (Sandbox Code Playgroud)
你可以用sparse它:
result = full(sparse(A, 1:numel(A), A));
Run Code Online (Sandbox Code Playgroud)
或者将结果矩阵初始化为零,然后使用以下方法填写A适当的位置sub2ind:
m = max(A);
n = numel(A);
result = zeros(m, n);
result(sub2ind([m n], A, 1:numel(A))) = A;
Run Code Online (Sandbox Code Playgroud)