Reputation: 53
I have a column vector in MATLAB and am trying to construct a matrix of differences with row-wise varying size of difference.
It is hard to explain in words, so I will illustrate with an example:
lets say my data is:
data = [ 1 2 3 4 5 6 ];
what i am trying to do, is make a matrix that takes the differences as such (each column difference size changes [increasing by one]):
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)]
My best guess of doing this was to make a triangle matrix with nested loops. My MATLAB code looks like this:
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
What I am trying to do is calculate the first column of differences with distance 1, then calculate the second column of differences with distance 2 and so on... To accommodate the necessary row values I need, I am using the "step" variable which is set to zero for calculating column one, I then want it to increase by 1 when calculating column 2 to have the correct dimensions. But I can not make it work. If I take the "step" out and use this:
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
everything works, but each column has the same distance of differences and it does not increase by one. Any ideas guys?
Upvotes: 3
Views: 407
Reputation: 6084
The problem with your solution is that it will only work with column vectors, because of the loop j = 1:1:size(data)-1
. The call of size
will return [1,6]
; then the -1 is applied yielding [0,5]
. Then only the first value of this vector is taken and in turn the for loop will only run from 1
to 1-1==0
, i.e. NOT.
Use numel
or size(.,1)
/size(.,2)
instead. (Also don't use semicola ;
after the loop initialization). (Try out the MATLAB debugger!)
Here is my take on how to repair your approach:
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
I like the use of gallery('circul',n:-1:1)
, in thewaywewalk's answer, I do however find the rest a bit too complicated.
Here is my take reusing his idea:
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
Upvotes: 1
Reputation: 25232
If I understand right, you want to do that:
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)))
so the output is:
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
Upvotes: 4