根据部分填充的向量形成“部分”的身份矩阵

时间:2018-06-19 13:36:02

标签: arrays matlab matrix vector matrix-multiplication

我目前正在按照以下方案从MATLAB中的向量形成矩阵:

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

x = [0 1 1 0 1]; 

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

  • Y具有m行,其中mx中的行数(此处为3)。
  • Y的每一行在第k项处填充一个,其中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

它有效,但是我有点不满意,因为它看起来效率低下且不够优雅。欢迎提出任何更平滑实现的想法,也许使用一些矩阵乘法。

5 个答案:

答案 0 :(得分:5)

以下是一些单行替代方法:

  • 使用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));
    

答案 1 :(得分:4)

使用find获得x中1的索引,它们也是Y中1的列下标。通过adding找到向量Y的所有元素的x行数。使用这些将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;

答案 2 :(得分:4)

这是使用矩阵乘法的另一种选择:

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的注释,它简化了代码。

答案 3 :(得分:1)

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

  1. (7.3e-4秒)server <- function(input, output) { observe({ file1=input$file1 if (is.null(file1)){ return(NULL) } df<-read.csv(file1$datapath) df$FAIL<-ifelse(df$OPERATION_STATUS %in% "FAIL",1,0) output$env<-renderPlot({ e <- df[which(df$CATEGORY %in% "OSV-ENVIRONMENT" & df$FAIL == 1),] p <- ggplot(e, aes(DATE, CRIT_CODE, color=as.factor(FAIL))) + geom_point(size=3) + labs(title="Environment Fails by Date") + theme_light() + theme(plot.title=element_text(hjust=0.5)) print(p) }) })
  2. (7.5e-4秒)full(sparse(1:nnz(x), find(x), 1));
  3. (7.7e-4秒)cols = find(x); noofones = sum(x); Y = zeros(noofones, size(x,2)); Y(sub2ind(size(Y), 1:noofones, cols)) = 1;
  4. (1.7e-3秒)Y = accumarray([(1:nnz(x)).' find(x(:))], 1);
  5. (3.1e-3秒)I = speye(numel(x)); Y = I .* x; Y = full(Y(logical(x), :));

答案 4 :(得分:1)

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

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

x的选项非常慢,但是在计算机上有10个元素的情况下,full(sparse(...的运行速度比x快。