基于向量创建逐行增加差异的矩阵

3

我在MATLAB中有一个列向量,想要构建一个差异矩阵,并且每行的差异大小不同。

用文字很难解释,我来用一个例子说明:

假设我的数据是:

data = [ 1 2 3 4 5 6 ];

我想做的是创建一个矩阵,其中取差异如下(每列差异大小均会改变[递增一)]:

diff = 
[(2 - 1) ...
 (3 - 2) (3 - 1) ...
 (4 - 3) (4 - 2) (4 - 1) ...
 (5 - 4) (5 - 3) (5 - 2) (5 - 1) ...
 (6 - 5) (6 - 4) (6 - 3) (6- 2) (6 - 1)]

我最好的猜测是使用嵌套循环创建一个三角形矩阵。我的MATLAB代码如下:

differences = zeros(length(data) - 1, length(data) - 1);
step = 0;  

for j = 1:1:size(data) - 1; 
    for i = 1:size(logquarterly) - 1 - step;

        if j <= i;
        differences(i,j) = data(i + 1 + step , 1) - data(i,1);
        step = step + 1;
        end

    end
end

我想要做的是计算距离为1的第一列差异,然后计算距离为2的第二列差异,以此类推... 为了容纳所需的行值,我使用了“步长”变量,在计算第一列时将其设置为零,然后当计算第二列时,我希望它增加1以获得正确的维度。但我无法使其正常工作。如果我去掉“步长”并使用以下内容:
differences = zeros(length(data) - 1, length(data) - 1);


for j = 1:1:size(data) - 1; 
    for i = 1:size(logquarterly) - 1;

        if j <= i;
        differences(i,j) = data(i + 1 , 1) - data(i,1);
        end

    end
end

一切都正常,但每个列之间的差距相同,且没有递增。有什么建议吗?


2
logquarterly是什么?为什么不将给定样本输入的最终期望值写下来?如果期望输出是一个二维数组,并且似乎会有空白空间,那么这些空间应该填充什么?也许可以使用一些随机的东西代替1、2、3、4、5、6作为输入元素? - Divakar
2个回答

4

如果我理解正确,您想做到这一点:

data = [ 1 2 3 4 5 6 ];
n = numel(data);

%// calculate differences
diffs = bsxfun(@minus, data(end:-1:1), data(end:-1:1).')  

%'
%// get linear indices from circulant sub-indices for rows and 
%// linear indices for columns
idx = sub2ind([n n], gallery('circul',n:-1:1), ndgrid(1:n,1:n))

%// mask output and get lower triangular matrix
output = tril(diffs(idx(n-1:-1:1,n-1:-1:1)))

因此,输出结果为:
output =

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

这个对我来说无法运行。你确定你的最后一个命令是 flip 吗?难道不应该是 flipud 或者 fliplr 吗? - kkuilla
@kkuilla,“flip”在较旧版本的Matlab中可能不可用,请查看我的编辑。 - Robert Seifert
1
很棒的技巧,我不知道这个函数 +1。 - Benoit_11

1
你的解决方案存在问题,因为循环 j = 1:1:size(data)-1 只能处理列向量。调用 size 将返回 [1,6];然后应用 -1 得到 [0,5]。然后只取此向量的第一个值,进而 for 循环将只从 1 运行到 1-1==0,即不运行。 请改用 numelsize(.,1)/size(.,2)。 (初始化循环后也不要使用分号 ;)。 (尝试使用 MATLAB 调试器!)
以下是我的修复方法:
differences = zeros(length(data)-1, length(data)-1);
for j = 1:size(differences,2) 
    for i = j:size(differences,1)
        differences(i,j) = data(i+1) - data(i-j+1);
    end
end

我喜欢在thewaywewalk的回答中使用gallery('circul',n:-1:1),但是我发现其余部分有点太复杂了。

以下是我对他的想法进行再利用的方式:

n = numel(data);
L = ndgrid(2:n,2:n);           % // Generate indices for Left side of operator
R = gallery('circul',1:n-1).'; %'// Generate indices for Right side of operator
out = tril(data(L) - data(R))  % // Do subtraction of corresponding indices

你太棒了!谢谢。 - gsardarian
有点想多了,对于非常大的数组(n > 5000),您的方法也稍微快一些。我已经投了赞成票 ;) - Robert Seifert
@thewaywewalk:我真的很喜欢使用 gallery('circul'),因为我以前从未见过它,所以我必须自己尝试一下。 :-) - knedlsepp
@knedlsepp 相册功能提供了许多其他可能性。不幸的是,文档非常糟糕,除非您了解所有测试函数的数学背景,否则很难浏览和使用它们。 - Robert Seifert
@thewaywewalk:看了一眼doc gallery后,我的想法完全一致。 - knedlsepp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接