如何在Matlab中沿对角线重复一个矢量

问题描述:

我想重复一个长度为n的矢量A在对角线上m次,以获得(n+m-1) x m矩阵B。举个例子,比如说A = [a;b;c;d],m = 4。这应该会导致如何在Matlab中沿对角线重复一个矢量

B = 
[a 0 0 0; 
b a 0 0; 
c b a 0; 
d c b a; 
0 d c b; 
0 0 d c; 
0 0 0 d] 

有关快速实现此目的的任何建议? blkdiag(repmat(A,1,m))在这种情况下不会帮助我,因为它会创建一个(n*m) x m矩阵。

最终我其实在第三矩阵C的矩阵产品DB只是感兴趣:

D=C*B 

如果你看到另一个选项获取D无需生成B,我将不胜感激。但是对于上述问题的解决方案也会让我感到非常高兴!顺便说一句,nm会很大。

谢谢!

+3

这看起来像一个换位托普利茨矩阵。我相信matlab有一个生成toeplitz矩阵的函数。这可能对你有用。 – mathematician1975

+0

@julian我的方法适合你吗?如果m和n是高值,它可以节省创建矩阵'B'的时间,并且将所有的零乘以那里......我只是真诚地知道它是否工作... – Adiel

笨拙的,但一般的单行

n = 3;  %number of elements in A; 
m = 5;  %repetitions 
A = (1:n); 

B = full(spdiags(repmat(A(:),1,m)' , 1-(1:n) , n+m-1, m)) 

回报:

B = 

    1  0  0  0  0 
    2  1  0  0  0 
    3  2  1  0  0 
    0  3  2  1  0 
    0  0  3  2  1 
    0  0  0  3  2 
    0  0  0  0  3 

可选地一种改进的,通用的rubenvb's solution

B = toeplitz([A(:);zeros(m-1,1)] , zeros(1,m)) 

在这两种情况下版本A可以be eithe r行或列向量。

更快的解决方案(因子2x)是spdiags的第一个!


编辑:甚至笨拙,但高达10倍比toeplitz -approach更快(这取决于N,M):

B = reshape([repmat([A(:);zeros(m,1)],m-1,1) ; A3(:)] ,[],m) 
+0

不幸的是'spdiags'不能处理矢量。 – julian

+0

@ julian:看看我最后一次编辑,这个解决方案比toeplitz方法快一点。 – thewaywewalk

+0

确实,你的最后一行比toeplitz更快,如果我的m和n的值非常高,那么它的速度会稍微快一点。谢谢! – julian

因为@ mathematician1975是懒得写一个合适的回答。

Matlab具有此功能,称为toeplitz

你会这样称呼它:

c=[1;2;3;4;0;0;0]; 
r=[0, 0, 0, 0]; 
toeplitz(c,r) 

ans = 

    1 0 0 0 
    2 1 0 0 
    3 2 1 0 
    4 3 2 1 
    0 4 3 2 
    0 0 4 3 
    0 0 0 4 

您可以用零起到塑造矩阵你想要的方式。

+1

这不是懒惰,我只是不记得什么论点 - 我总是发现写一个评论比发表一个不正确的答案更好!无论如何,你从我身上得到+1 – mathematician1975

+0

@ mathematician1975足够公平':-p'谢谢! – rubenvb

没有矩阵B的总解决方案是对C的每一行与A进行卷积。你可以通过循环做到这一点:

for k=1:size(C,1) 
    D(k,:)=conv(C(k,:),A'); 
end 
D=D(:,length(A)-1:end-length(A)+1); % elliminate the convolution edges 

我认为它也可以完成,无需环路,由arrayfun

k=1:size(C,1); 
D=arrayfun(@(x) conv(C(x,:),A'), k); 
D=D(:,length(A)-1:end-length(A)+1); % elliminate the convolution edges 
+0

就我所见,卷积只给出了上面对于对称“A”(例如'[a b b a])所要求的结果。我的'A'实际上是对称的,所以这不成问题。你的for循环比rubenvb的解决方案慢很多,但实际上比你的'arrayfun'版本要快,它必须被扩展为:'colNoise = cell2mat(arrayfun(@(x)conv(C(x,:), A','valid')',k,'UniformOutput',0))';' – julian

+0

'valid'保存最后一行消除边缘。 'UniformOutput'是必要的,因为输出是一个向量而不是标量。即使我会改变我的数据格式,因此可以摆脱所有“''''”,这仍然比较慢。但仍然非常感谢你的建议 – julian

+0

当然我的意思是'D'而不是colNoise在第一个评论中......复制和粘贴错误... – julian