Matlab将向量转换为二进制矩阵 [英] Matlab Convert Vector to Binary Matrix

查看:163
本文介绍了Matlab将向量转换为二进制矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个向量v,大小为(m,1),其元素是从1:n中选取的整数.我想创建一个大小为(m,n)的矩阵M,如果v(i)= j,则其元素M(i,j)为1,否则为0.我不想使用循环,而只想将其实现为简单的矢量矩阵操作.

I have a vector v of size (m,1) whose elements are integers picked from 1:n. I want to create a matrix M of size (m,n) whose elements M(i,j) are 1 if v(i) = j, and are 0 otherwise. I do not want to use loops, and would like to implement this as a simple vector-matrix manipulation only.

所以我首先想到的是创建一个包含重复元素的矩阵

So I thought first, to create a matrix with repeated elements

 M = v * ones(1,n) % this is a (m,n) matrix of repeated v

例如v = [1,1,3,2]' m = 4和n = 3

For example v=[1,1,3,2]' m = 4 and n = 3

M =
     1     1     1
     1     1     1
     3     3     3
     2     2     2

然后我需要创建一个大小为(1,n)的比较向量c

then I need to create a comparison vector c of size (1,n)

c = 1:n
1 2 3

然后我需要执行一系列逻辑比较

Then I need to perform a series of logical comparisons

M(1,:)==c % this results in [1,0,0]
.
M(4,:)==c % this results in [0,1,0]

但是,我认为应该以紧凑矩阵表示法执行每行的最后一步,但是我很困惑,对索引的知识还不够. 最终结果应该是

However, I thought it should be possible to perform the last steps of going through each single row in compact matrix notation, but I'm stumped and not knowledgeable enough about indexing. The end result should be

M =
     1     0     0
     1     0     0
     0     0     1
     0     1     0

推荐答案

A very simple call to bsxfun will do the trick:

>> 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

代码的工作原理实际上非常简单. bsxfun是所谓的 B 单个 S ingleton E X 扩展功能.它的作用是,您可以提供两个任意大小的数组/矩阵,只要它们可以可广播即可.这意味着它们需要能够扩展大小,以便它们两者的大小相等.在这种情况下,v是您感兴趣的向量,并且是第一个参数-请注意,它已转置.第二个参数是从1到n的向量.现在将发生的事情是,列向量v复制/扩展以获得与n一样多的值,第二个向量被复制了多达在v中.然后,我们在这两个数组之间执行eq/equals运算符.实际上,此扩展矩阵在第一列中具有全1,在第二列中具有全2,直到n.通过在这两个矩阵之间进行eq运算,实际上可以确定v中的哪些值等于相应的列索引.

How the code works is actually quite simple. bsxfun is what is known as the Binary Singleton EXpansion function. What this does is that you provide two arrays / matrices of any size, as long as they are broadcastable. This means that they need to be able to expand in size so that both of them equal in size. In this case, v is your vector of interest and is the first parameter - note that it's transposed. The second parameter is a vector from 1 up to n. What will happen now is the column vector v gets replicated / expands for as many values as there are n and the second vector gets replicated for as many rows as there are in v. We then do an eq / equals operator between these two arrays. This expanded matrix in effect has all 1s in the first column, all 2s in the second column, up until n. By doing an eq between these two matrices, you are in effect determining which values in v are equal to the respective column index.

这里是详细的时间测试和每个功能的细目分类.我将每个实现放入一个单独的函数中,还让n=max(v)起作用,以便Luis的第一个代码起作用.我使用 timeit 为每个功能计时:

Here is a detailed time test and breakdown of each function. I placed each implementation into a separate function and I also let n=max(v) so that Luis's first code will work. I used timeit to time each function:

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

此测试假设n = 10000,向量v是10000 x 1向量,其随机分布的整数从1到1000.顺便说一句,我不得不修改Luis的第二个函数,以便索引可以按加法要求工作兼容尺寸的向量.

This test assumes n = 10000 and the vector v is a 10000 x 1 vector of randomly distributed integers from 1 up to 1000. BTW, I had to modify Luis's second function so that the indexing will work as the addition requires vectors of compatible dimensions.

运行此代码,我们得到:

Running this code, we get:

>> timing_binary
Luis Mendo - Sparse: 0.015086
Luis Mendo - Indexing: 0.327993
rayryeng - bsxfun: 0.040672
OP: 0.841827

路易斯·门多(Luis Mendo)的sparse代码获胜(正如我预期的那样),其次是bsxfun,随后是索引,最后是您建议的使用矩阵运算的方法.时间以秒为单位.

Luis Mendo's sparse code wins (as I expected), followed by bsxfun, followed by indexing and followed by your proposed approach using matrix operations. The timings are in seconds.

这篇关于Matlab将向量转换为二进制矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆