gci*_*ani 4 arrays matlab vector matrix matrix-indexing
我有一个大小为(m,1)的向量v,其元素是从1:n中选取的整数.我想创建一个大小为(m,n)的矩阵M,如果v(i)= j则其元素M(i,j)为1,否则为0.我不想使用循环,并希望仅将其实现为简单的向量矩阵操作.
所以我首先考虑创建一个包含重复元素的矩阵
M = v * ones(1,n) % this is a (m,n) matrix of repeated v
Run Code Online (Sandbox Code Playgroud)
例如,v = [1,1,3,2]'m = 4且n = 3
M =
1 1 1
1 1 1
3 3 3
2 2 2
Run Code Online (Sandbox Code Playgroud)
然后我需要创建一个大小为(1,n)的比较向量c
c = 1:n
1 2 3
Run Code Online (Sandbox Code Playgroud)
然后我需要进行一系列逻辑比较
M(1,:)==c % this results in [1,0,0]
.
M(4,:)==c % this results in [0,1,0]
Run Code Online (Sandbox Code Playgroud)
但是,我认为应该可以在紧凑矩阵表示法中执行遍历每一行的最后步骤,但是我很难理解并且对索引不够了解.最终结果应该是
M =
1 0 0
1 0 0
0 0 1
0 1 0
Run Code Online (Sandbox Code Playgroud)
一个非常简单的电话bsxfun
会做的伎俩:
>> n = 3;
>> v = [1,1,3,2].';
>> M = bsxfun(@eq, v, 1:n)
M =
1 0 0
1 0 0
0 0 1
0 1 0
Run Code Online (Sandbox Code Playgroud)
代码如何工作实际上非常简单. bsxfun
是所谓的乙 inary 小号 ingletonË X潘申功能.这样做是为了提供任意大小的两个数组/矩阵,只要它们是可广播的.这意味着它们需要能够扩大尺寸,以使它们的尺寸相等.在这种情况下,v
你的感兴趣的矢量是第一个参数 - 注意它是转置的.第二个参数是从1到1的向量n
.现在将发生的是列向量v
被复制/扩展为尽可能多的值n
并且第二个向量被复制为与这两个数组之间的/ equals运算符一样多的行.这个扩展矩阵实际上在第一列中全部为1,在第二列中全部为2,直到.通过在这两个矩阵之间进行操作,您实际上确定哪些值等于相应的列索引.v
.然后我们执行eq
n
eq
v
这是每个功能的详细时间测试和细分.我将每个实现放在一个单独的函数中,我也让n=max(v)
Luis的第一个代码可以工作.我曾经timeit
为每个功能计时:
function timing_binary
n = 10000;
v = randi(1000,n,1);
m = numel(v);
function luis_func()
M1 = full(sparse(1:m,v,1));
end
function luis_func2()
%m = numel(v);
%n = 3; %// or compute n automatically as n = max(v);
M2 = zeros(m, n);
M2((1:m).' + (v-1)*m) = 1;
end
function ray_func()
M3 = bsxfun(@eq, v, 1:n);
end
function op_func()
M4= ones(1,m)'*[1:n] == v * ones(1,n);
end
t1 = timeit(@luis_func);
t2 = timeit(@luis_func2);
t3 = timeit(@ray_func);
t4 = timeit(@op_func);
fprintf('Luis Mendo - Sparse: %f\n', t1);
fprintf('Luis Mendo - Indexing: %f\n', t2);
fprintf('rayryeng - bsxfun: %f\n', t3);
fprintf('OP: %f\n', t4);
end
Run Code Online (Sandbox Code Playgroud)
该测试假设n = 10000
并且向量v
是从1到1000的随机分布整数的10000 x 1向量.顺便说一下,我必须修改Luis的第二个函数,以便索引将起作用,因为加法需要兼容维度的向量.
运行此代码,我们得到:
>> timing_binary
Luis Mendo - Sparse: 0.015086
Luis Mendo - Indexing: 0.327993
rayryeng - bsxfun: 0.040672
OP: 0.841827
Run Code Online (Sandbox Code Playgroud)
Luis Mendo的sparse
代码获胜(如我所料),bsxfun
接着是索引,然后是使用矩阵运算的建议方法.时间以秒为单位.