MATLAB diff function with matrices of unequal dimensions - matlab

I read MATLAB diff.m readme, still couldn't figure out the following:
a = [1 2 3]'
b = [3 2 1 4; 1 1 1 5; 5 5 5 6]
diff([a b]') =
2 -1 2
-1 0 0
-1 0 0
3 4 1
what rule is MATLAB applying here? does MATLAB apply different rule if one of the matrices (i.e. a or b) is logical matrix? or both a and b are logical matrix?

MATLAB applies the same rule regardless of the input matrices. Run your code line-by-line in the command window and see.
a and b are like this:
>> a = [1 2 3]'
a =
1
2
3
>> b = [3 2 1 4; 1 1 1 5; 5 5 5 6]
b =
3 2 1 4
1 1 1 5
5 5 5 6
then [a b]':
>> [a b]'
ans =
1 2 3
3 1 5
2 1 5
1 1 5
4 5 6
Now apply the diff rule on this as follows:
[ row 2 - row 1 ]
[ row 3 - row 2 ]
[ row 4 - row 3 ]
[ row 5 - row 4 ]
you will get
>> diff([a b]')
ans =
2 -1 2
-1 0 0
-1 0 0
3 4 1

a =
[1
2
3]
So,
[a b] =
[ 1 3 2 1 4
2 1 1 1 5
3 5 5 5 6 ]
and thus
[a b]' =
[ 1 2 3
3 1 5
2 1 5
1 1 5
4 5 6 ]
and then diff takes the differences along the first dimension whose size is not 0 (i.e. down each column).
This gives the result
diff([a b]') =
[ 2 -1 2
-1 0 0
-1 0 0
3 4 1 ].

Related

Iterate one vector through another in Matlab Part 2

This is a similar request to my post at Iterate one vector through another in Matlab
I am using Luis' suggestion with the following code:
E=[1 2 3 4 5 6 7 8 9 10];
A = [1 2];
s = size(E,2);
t = numel(A);
C = cell(1,s);
[C{:}] = ndgrid(A);
C = cat(s+1, C{:});
C = fliplr(reshape(C, t^s, s));
This produces a good result for C as a 1024x10 matrix with all possible permutations of 1 and 2 to a length of 10 columns. What I want to do is remove any rows that are not in increasing order. For example now I get:
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 2 1
1 1 1 1 1 1 1 1 2 2
All are valid except for the third row since it goes from 2 to back to 1.
I have code to get the desired result, but it is very slow and inefficient.
E=[1 2 3 4 5 6 7 8 9 10];
A = [1 2];
s = size(E,2);
t = numel(A);
C = cell(1,s);
[C{:}] = ndgrid(A);
C = cat(s+1, C{:});
C = fliplr(reshape(C, t^s, s));
min=0;
for row=1:size(C,1)
for col=1:size(C,2)
if(C(row,col)>min)
min=C(row,col);
elseif(C(row,col)<min)
C(row,:)=0;
continue;
end
end
min=0;
end
C = C(any(C,2),:); %remove all zero rows
The desired output is now:
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 2 2
1 1 1 1 1 1 1 2 2 2
1 1 1 1 1 1 2 2 2 2
1 1 1 1 1 2 2 2 2 2
1 1 1 1 2 2 2 2 2 2
1 1 1 2 2 2 2 2 2 2
1 1 2 2 2 2 2 2 2 2
1 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
Any ideas on how to optimize my code so I do not need to use nested loops?
The super-simple but not-quite-so-obvious solution via a couple of row-wise operations:
d = diff(C, [], 2);
m = min(d, [], 2);
C = C(m>=0, :);
Of course, in this particular example it would be far easier to just generate the resulting matrix directly:
C = flipud(triu(ones(s+1,s).*(max(A)-min(A))) + min(A));
but I assume you're also interested in less trivial values of A ;)

MATLAB: How do you add all the first n rows of a matrix within the same column, and save the result to the last row?

It was hard to phrase the question, but here's an example of what I'm looking for:
1 2 3 4
2 1 1 1
2 2 3 1
0 0 0 0
and in column one, I add all the value of all of the first three rows and save it to the third and so on, so that it becomes:
1 2 3 4
2 1 1 1
2 2 3 1
5 5 7 6
I think you can use sum:
octave:23> m = [1 2 3 4; 2 1 1 1; 2 2 3 1; 0 0 0 0]
m =
1 2 3 4
2 1 1 1
2 2 3 1
0 0 0 0
octave:24> m(length(m), :) = sum(m)
m =
1 2 3 4
2 1 1 1
2 2 3 1
5 5 7 6

Matrix creation Octave / Matlab, loopless solution request

I want to create a matrix like
A = [0 0 0 0 1;
0 0 0 1 1;
0 0 0 1 1;
0 0 0 1 1;
0 0 1 1 1;
0 1 1 1 1]
based on a vector indicating how many '0's should precede '1's on each row:
B = [4 3 3 3 2 1]
Is there a loopless way to do this ?
You don't mention in your question how the horizontal size of the array should be defined (the number of ones).
For predefined width you can use this code:
width = 5;
A = cell2mat(arrayfun(#(x) [ zeros(1,x), ones(1,width-x) ], B, 'UniformOutput', false)');
If you want that A has minimal width, but still at least one 1 in every row:
A = cell2mat(arrayfun(#(x) [ zeros(1,x), ones(1,max(B)+1-x) ], B, 'UniformOutput', false)');
A shorter “old-school” way to achieve this without a loop would be as follows:
A = repmat(B',1,max(B)+1)<repmat([1:max(B)+1],size(B,2),1)
If you want to have a minimum number of ones
min_ones=1; %or whatever
A = repmat(B',1,max(B)+min_ones)<repmat([1:max(B)+min_ones],size(B,2),1)
I don’t know how this compares speedwise to #nrz’s approach (I’ve only got Octave to hand right now), but to me it's more intuitive as it’s simply comparing a max(B) + min_ones * column tiling of B:
4 4 4 4 4
3 3 3 3 3
3 3 3 3 3
3 3 3 3 3
2 2 2 2 2
1 1 1 1 1
with a row tiling of [1 : max(B) + min_ones]
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
To generate:
A =
0 0 0 0 1
0 0 0 1 1
0 0 0 1 1
0 0 0 1 1
0 0 1 1 1
0 1 1 1 1
This requires only one line, and seems to be faster than previous solutions based on repmat or arrayfun:
%// Example data
ncols = 5;
B = [4 3 3 3 2 1];
%// Generate A
A = bsxfun(#gt, 1:ncols, B(:));

Replace duplicate elements from vector with 0 (Matlab/Octave)

I want to replace duplicate elements from a vector with 0, and keep only the first occurrence.
If I have a vector like
[ 1 1 2 2 2 3 3 3 4 4 4 4 5 5 5 5 6 6 6 ]
how could I transform it into
[ 1 0 2 0 0 3 0 0 4 0 0 0 5 0 0 0 6 0 0 ] ?
Thanks.
a = [ 1 1 2 2 2 3 3 3 4 4 4 4 5 5 5 5 6 6 6 ];
[c, ia] = unique(a, 'first');
t = a;
t(ia) = 0;
filtered_vect = a - t;
edit: That in a more concise way, destroying the original vector:
a = [ 1 1 2 2 2 3 3 3 4 4 4 4 5 5 5 5 6 6 6 ];
[c, ia] = unique(a, 'first');
a(~ismember(1:length(a),ia)) = 0;

Is it possible to delete elements from matlab matrix?

I have a matlab matrix in the form
A = [1 2 3 4 5 6; 1 1 2 2 3 3; 1 2 3 3 2 1]
Is it possible to delete the 4th, 5th and 6th columns of the matrix A so that the result would be:
A = [1 2 3; 1 1 2; 1 2 3]
This would do it:
A(:,4:6)=[];
octave-3.4.0:1> A = [1 2 3 4 5 6; 1 1 2 2 3 3; 1 2 3 3 2 1]
A =
1 2 3 4 5 6
1 1 2 2 3 3
1 2 3 3 2 1
octave-3.4.0:2> A = A(:,1:3)
A =
1 2 3
1 1 2
1 2 3