Matlab将矢量转换为二进制矩阵

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)

ray*_*ica 5

一个非常简单的电话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.然后我们执行eqneqv


这是每个功能的详细时间测试和细分.我将每个实现放在一个单独的函数中,我也让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接着是索引,然后是使用矩阵运算的建议方法.时间以秒为单位.