在 MATLAB 中用列向量给出的索引创建矩阵的向量化方法
Vectorized approach to creating a matrix with 1s in indices given by a column vector in MATLAB
假设我得到一个 1000x1
的列向量,其值范围为 1-10。现在我想把它变成一个 1000x10
矩阵,其中对于每一行,列向量中的值给定的列中都有一个 1。我在下面有一个正确的实现,但是有没有一种优雅的方法可以在没有 for
循环的情况下做到这一点?
ymat = zeros(1000, 10);
y = randi([1,10],1000,1);
for i=1:1000
ind = y(i);
ymat(i,ind)=1;
end
当然可以。使用 repmat
和 bsxfun
。例如,
bsxfun(@eq,repmat(1:10,numel(y),1),repmat(y,1,10))
答案:
...
0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 1
0 0 0 0 1 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0
>>
您有一组列索引,对应的行索引应该是1:1000
。
有两个选项可以从中生成矩阵。
accumarray
稀疏
acccumarray 将生成 full 矩阵,sparse 将生成 sparse 矩阵。
在您的情况下,生成的矩阵密度为 10%,可以视为稀疏矩阵。
% Full matrix using accumarray
ymat = accumarray([(1:1000).', y], ones(1000,1), [1000, 10]);
% Sparse matrix using sparse
ymat = sparse(1:1000, y, ones(1000,1), 1000, 10, 1000);
计算时间
我 运行 带有 y = 1000 x 1
和 y = 10000 x 1
的代码。
- y = 1000 x 1
- y = 10000 x 1
我添加了@transversality 条件建议的代码。
原来accumarray
最快,sparse
最慢
accumarray
显示较小尺寸的更好性能,但 accumarray
和 bsxfun(@eq)
之间的差距随着我们增加数组的大小而变小。
我们可以使用这些条目的“linear index”一次访问 ymat 中条目的任何子集。由于我们已经有了包含列坐标的y,而行坐标只是1:100,我们可以很容易地用sub2ind
得到它们的线性索引值,然后将[=中的所有索引值设置为1 12=]:
ymat(sub2ind([1000 10], (1:1000)', y)) = 1
但是请注意,必须事先创建具有适当大小的 ymat
。
您还可以使用ind2vec
函数:
ymat=full(ind2vec(y.').')
假设我得到一个 1000x1
的列向量,其值范围为 1-10。现在我想把它变成一个 1000x10
矩阵,其中对于每一行,列向量中的值给定的列中都有一个 1。我在下面有一个正确的实现,但是有没有一种优雅的方法可以在没有 for
循环的情况下做到这一点?
ymat = zeros(1000, 10);
y = randi([1,10],1000,1);
for i=1:1000
ind = y(i);
ymat(i,ind)=1;
end
当然可以。使用 repmat
和 bsxfun
。例如,
bsxfun(@eq,repmat(1:10,numel(y),1),repmat(y,1,10))
答案:
...
0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 1
0 0 0 0 1 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0
>>
您有一组列索引,对应的行索引应该是1:1000
。
有两个选项可以从中生成矩阵。
accumarray
稀疏
acccumarray 将生成 full 矩阵,sparse 将生成 sparse 矩阵。
在您的情况下,生成的矩阵密度为 10%,可以视为稀疏矩阵。
% Full matrix using accumarray
ymat = accumarray([(1:1000).', y], ones(1000,1), [1000, 10]);
% Sparse matrix using sparse
ymat = sparse(1:1000, y, ones(1000,1), 1000, 10, 1000);
计算时间
我 运行 带有 y = 1000 x 1
和 y = 10000 x 1
的代码。
- y = 1000 x 1
- y = 10000 x 1
我添加了@transversality 条件建议的代码。
原来accumarray
最快,sparse
最慢
accumarray
显示较小尺寸的更好性能,但 accumarray
和 bsxfun(@eq)
之间的差距随着我们增加数组的大小而变小。
我们可以使用这些条目的“linear index”一次访问 ymat 中条目的任何子集。由于我们已经有了包含列坐标的y,而行坐标只是1:100,我们可以很容易地用sub2ind
得到它们的线性索引值,然后将[=中的所有索引值设置为1 12=]:
ymat(sub2ind([1000 10], (1:1000)', y)) = 1
但是请注意,必须事先创建具有适当大小的 ymat
。
您还可以使用ind2vec
函数:
ymat=full(ind2vec(y.').')