【问题标题】:Forming a 'partial' identity-matrix according to a partially filled vector根据部分填充的向量形成“部分”身份矩阵
【发布时间】:2018-06-19 13:36:02
【问题描述】:

我目前正在 MATLAB 中按照下面描述的方案从向量形成一个矩阵:

Given 是一个向量x,包含任意顺序的 1 和 0,例如

x = [0 1 1 0 1]; 

由此,我想形成一个矩阵Y,描述如下:

  • Y 具有 m 行,其中 mx 中的行数(此处为:3)。
  • Y 的每一行在k-th 条目处填充一个 1,其中 k 是向量 x 中一个 1 的位置(此处为:k = 2,3,5
  • 对于上面的示例x,这将导致:

    Y = [0 1 0 0 0;
         0 0 1 0 0; 
         0 0 0 0 1]
    

    这与单位矩阵相同,它的第 (x=0) 行已被消除。

我目前正在通过以下代码实现此目的:

x = [0,1,1,0,1]; %example from above
m = sum(x==1);
Y = zeros(m,numel(x));
p = 1;
for n = 1:numel(x)
    if x(n) == 1 
       Y(p,n) = 1;
       p = p+1;
    end  
end

它有效,但我对它有点不满意,因为它似乎效率低下且不雅。欢迎任何关于更顺畅实现的想法,可能使用一些矩阵乘法等。

【问题讨论】:

    标签: arrays matlab matrix vector matrix-multiplication


    【解决方案1】:

    这里有一些单行替代方案:

    • 使用sparse

      Y = full(sparse(1:nnz(x), find(x), 1));
      
    • 类似但与accumarray:

      Y = accumarray([(1:nnz(x)).' find(x(:))], 1);
      
    • 使用eye 和索引。这假设 Y 以前未定义:

      Y(:,logical(x)) = eye(nnz(x));
      

    【讨论】:

      【解决方案2】:

      使用find获取x中1的索引,同时也是Y中1的列下标。通过adding向量x的所有元素求Y的行数。使用这些将Y 初始化为zero matrix。现在使用sub2ind 找到放置 1 的线性索引。 Use these indicesY 的元素改为1。

      cols = find(x);
      noofones = sum(x);
      Y = zeros(noofones, size(x,2));
      Y(sub2ind(size(Y), 1:noofones, cols)) = 1;
      

      【讨论】:

        【解决方案3】:

        这是使用矩阵乘法的替代方法:

        x = [0,1,1,0,1];
        I = eye(numel(x));
        
        % construct identity matrix with zero rows
        Y = I .* x;   % uses implicit expansion from 2016b or later
        Y = Y(logical(x), :);   % take only non-zero rows of Y
        

        结果:

        Y =
           0   1   0   0   0
           0   0   1   0   0
           0   0   0   0   1
        

        感谢@SardarUsama 的评论让代码稍微简化了一点。

        【讨论】:

        • Y = Y(logical(x), :); 代替Y = Y(logical(I*x.'), :); 怎么样?
        【解决方案4】:

        感谢大家提供不错的选择!对于随机(1000 个条目)x 向量,我尝试了您的所有解决方案和平均执行时间超过 1e4 次。结果如下:

        1. (7.3e-4 秒)full(sparse(1:nnz(x), find(x), 1));
        2. (7.5e-4 秒)cols = find(x); noofones = sum(x); Y = zeros(noofones, size(x,2)); Y(sub2ind(size(Y), 1:noofones, cols)) = 1;
        3. (7.7e-4 秒)Y = accumarray([(1:nnz(x)).' find(x(:))], 1);
        4. (1.7e-3 秒)I = speye(numel(x)); Y = I .* x; Y = full(Y(logical(x), :));
        5. (3.1e-3 秒)Y(:,logical(x)) = eye(nnz(x));

        【讨论】:

          【解决方案5】:

          根据您的评论“这与一个单位矩阵相同,它的第 (x=0) 行已消除。”,您也可以这样显式生成它:

          Y = eye(length(x));
          Y(x==0, :) = [];
          

          x 的选项非常慢,但在我的计算机上有 10 个元素的情况下,它比 full(sparse(...x 稍快。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-12-26
            • 2014-11-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-05-20
            • 2014-03-22
            相关资源
            最近更新 更多