根据部分填充的向量形成 'partial' 单位矩阵
Forming a 'partial' identity-matrix according to a partially filled vector
我目前正在 MATLAB 中按照下面描述的方案从向量形成矩阵:
给定一个向量 x
包含任意顺序的 1 和 0,例如
x = [0 1 1 0 1];
据此,我想形成一个矩阵Y
,描述如下:
Y
有 m
行,其中 m
是 x
中的行数(此处:3
)。
Y
的每一行在第 k
个条目处填充一个 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
它可以工作,但我对它有点不满意,因为它看起来效率低下且不够优雅。欢迎任何关于更流畅实施的想法,例如使用一些矩阵乘法等。
用find
to obtain the indices of ones in x
which are also the column subscripts of ones in Y
. Find the number of rows of Y
by adding all the elements of the vector x
. Use these to initialise Y
as a zero matrix. Now find the linear indices to place 1s using sub2ind
. Use these indices把Y
的元素改成1.
cols = find(x);
noofones = sum(x);
Y = zeros(noofones, size(x,2));
Y(sub2ind(size(Y), 1:noofones, cols)) = 1;
这是使用矩阵乘法的替代方法:
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 对代码进行了一些简化的评论。
这里有几个单行选项:
使用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));
感谢大家提供不错的选择!我尝试了您所有的解决方案,并为随机(1000 个条目)x 向量执行了超过 1e4 次的平均执行时间。以下是结果:
- (7.3e-4 秒)
full(sparse(1:nnz(x), find(x), 1));
- (7.5e-4 秒)
cols = find(x);
noofones = sum(x);
Y = zeros(noofones, size(x,2));
Y(sub2ind(size(Y), 1:noofones, cols)) = 1;
- (7.7e-4 秒)
Y = accumarray([(1:nnz(x)).' find(x(:))], 1);
- (1.7e-3 秒)
I = speye(numel(x));
Y = I .* x;
Y = full(Y(logical(x), :));
- (3.1e-3 秒)
Y(:,logical(x)) = eye(nnz(x));
根据您的评论 "This is identical to an identity matrix, that has its (x=0)th rows eliminated.",好吧,您也可以这样明确地生成它:
Y = eye(length(x));
Y(x==0, :) = [];
长 x
的选项非常慢,但在我的计算机上有 10 个元素的 x
时,它的运行速度比 full(sparse(...
稍快。
我目前正在 MATLAB 中按照下面描述的方案从向量形成矩阵:
给定一个向量 x
包含任意顺序的 1 和 0,例如
x = [0 1 1 0 1];
据此,我想形成一个矩阵Y
,描述如下:
Y
有m
行,其中m
是x
中的行数(此处:3
)。Y
的每一行在第k
个条目处填充一个 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
它可以工作,但我对它有点不满意,因为它看起来效率低下且不够优雅。欢迎任何关于更流畅实施的想法,例如使用一些矩阵乘法等。
用find
to obtain the indices of ones in x
which are also the column subscripts of ones in Y
. Find the number of rows of Y
by adding all the elements of the vector x
. Use these to initialise Y
as a zero matrix. Now find the linear indices to place 1s using sub2ind
. Use these indices把Y
的元素改成1.
cols = find(x);
noofones = sum(x);
Y = zeros(noofones, size(x,2));
Y(sub2ind(size(Y), 1:noofones, cols)) = 1;
这是使用矩阵乘法的替代方法:
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 对代码进行了一些简化的评论。
这里有几个单行选项:
使用
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));
感谢大家提供不错的选择!我尝试了您所有的解决方案,并为随机(1000 个条目)x 向量执行了超过 1e4 次的平均执行时间。以下是结果:
- (7.3e-4 秒)
full(sparse(1:nnz(x), find(x), 1));
- (7.5e-4 秒)
cols = find(x); noofones = sum(x); Y = zeros(noofones, size(x,2)); Y(sub2ind(size(Y), 1:noofones, cols)) = 1;
- (7.7e-4 秒)
Y = accumarray([(1:nnz(x)).' find(x(:))], 1);
- (1.7e-3 秒)
I = speye(numel(x)); Y = I .* x; Y = full(Y(logical(x), :));
- (3.1e-3 秒)
Y(:,logical(x)) = eye(nnz(x));
根据您的评论 "This is identical to an identity matrix, that has its (x=0)th rows eliminated.",好吧,您也可以这样明确地生成它:
Y = eye(length(x));
Y(x==0, :) = [];
长 x
的选项非常慢,但在我的计算机上有 10 个元素的 x
时,它的运行速度比 full(sparse(...
稍快。