Split vector to multiple vectors - matlab

I'm looking for a simple method to transforming a vector of the following type
[1 1 0 1 1]
To this group of vectors:
[0 0 0 0 1]
[0 0 0 1 0]
[0 1 0 0 0]
[1 0 0 0 0]
The vector itself represents polynomial coefficients (x^4 + x^3 + x + 1)
Thanks

Here are some approaches. Input is a vector v, output is a matrix M:
[~, rr, vv] = find(v);
M = full(sparse(1:nnz(v), flip(rr), 1));
M = flip(eye(numel(v)));
M = M(logical(v),:)
M = zeros(nnz(v), numel(v));
M(sub2ind(size(M), 1:size(M,1), flip(find(v)))) = 1;
M = double(bsxfun(#eq, flip(find(v(:))), 1:numel(v)));

Related

Matlab - How to perform operations on each row between two matrices?

I have two matrices each of which contains two vectors (each row is a vector):
u = [1 0 0; 2 0 0]
v = [1 1 0; 2 2 0]
I want to calculate two angles between the vectors of the corresponding rows in the matrices (angle between [1 0 0] , [1 1 0] and angle between [2 0 0] , [2 2 0]). In this example, both angles will be 45 degrees. So what I want is a new matrix like this:
angles = [45; 45]
When I try this:
u = [1 0 0; 2 0 0]
v = [1 1 0; 2 2 0]
dp = u(:,1) .* v(:,1) + u(:,2) .* v(:,2) + u(:,3) .* v(:,3);
angles = atan2d(norm(cross(u,v)),dp)
The anwser will be:
angles = [76.3670 ; 45.8683]
and when I try this (change norm to normr):
u = [1 0 0; 2 0 0]
v = [1 1 0; 2 2 0]
dp = u(:,1) .* v(:,1) + u(:,2) .* v(:,2) + u(:,3) .* v(:,3);
angles = atan2d(norm(crossr(u,v)),dp)
The anwser will be:
angles = [0 0 45.0000 ; 0 0 14.0362]
How can I make it calculate the angle between the vectors of each row?
Try:
u=[1 0 0;2 0 0];
v = [1 1 0;2 2 0];
atan2(cross(u,v,2),dot(u,v,2)) % radians
atan2d(cross(u,v,2),dot(u,v,2)) % degrees
The ,2 in the cross and dot functions specifies the dimension to operate, since you are storing each vector in a row.
There a discussion here, with many other ways to calculate, and you may find one more suitable to your particular case of application.

Create a special diagonal matrix

I want to create a special diagonal matrix in MATLAB that
uses [1 1] or any other array as main diagonal elements.
Something like the following:
[1 1 0 0 0 0
0 0 1 1 0 0
0 0 0 0 1 1]
How can I do that without using any loop structures?
Let
v = [1 1];
n = 3;
Using kron:
result = kron(eye(n), v);
Using blkdiag:
vv = repmat({v}, 1, n);
result = blkdiag(vv{:});

how can I vectorize setting the index values to one in Matlab?

I have the following loop that does what I need:
> whos Y
Name Size Bytes Class Attributes
Y 10x5000 400000 double
> whos y
Name Size Bytes Class Attributes
y 5000x1 40000 double
Y = zeros(K,m);
for i=1:m
Y(y(i),i)=1;
end
I would like to vectorize it and I have tried without success e.g.
Y = zeros(K,m);
Y(y,:)=1;
The idea is to get a vector of:
y = [9, 8, 7, .. etc]
and convert it to:
Y = [[0 0 0 0 0 0 0 0 1 0]' [0 0 0 0 0 0 0 1 0 0]' [0 0 0 0 0 0 1 0 0 0]' ... etc]
this I need in the context of a multi-class ANN implementation.
Have you considered using sparse matrix?
n=numel(y);
Y = sparse( y, 1:n, 1, n, n );
If you really must have the full matrix, you can call
Y = full(Y);
Here's one solution you could use. It's a starting point from which you could optimise
k = 10;
n = 20;
y = randi(k, 1, n);
columns = 1:n;
offsets = k*(columns-1);
indices = offsets + y;
Y = zeros(k, n);
Y(indices) = 1

Generate boolean matrix by predicate on row and column

I have the following vector:
y = [1; 3; 2; 3; 1];
All its values are between 1 and n (in this case, 3) and denote different options.
I want to create a matrix of size size(y, 1) x n whose rows correpond to y values:
1 0 0 % because y(1) = 1
0 0 1 % because y(2) = 3
0 1 0 % because y(3) = 2
0 0 1
1 0 0
One way to do this would be
Y = zeros(size(y, 1), num_labels);
for i = 1:m
Y(i, y(i)) = 1;
end
Is there a better way to do this, maybe in a single expression?
Basically, what I need is to generate a matrix with boolean predicate (i, j) => j == y(i).
You can try this if a is a column vector
a = [1; 3; 2; 3; 1];
bsxfun(#eq, a, [1:max(a)])
and this if it is a row vector
a = [1; 3; 2; 3; 1]';
bsxfun(#eq, a', [1:max(a)])
If you have access to Statistics Toolbox, the command dummyvar does exactly what you need.
>> y = [1; 3; 2; 3; 1];
>> dummyvar(y)
ans =
1 0 0
0 0 1
0 1 0
0 0 1
1 0 0
You can use sub2ind after initializing the matrix as follows:
y = [1; 3; 2; 3; 1];
m = length(y);
n = max(y);
Y = zeros(m, n);
Y(sub2ind(size(Y), 1:m, y')) = 1
Y =
1 0 0
0 0 1
0 1 0
0 0 1
1 0 0
The trick here is to know that the corresponding rows of y go from 1 to m one by one.
accumarray([(1:length(y)).' y], 1)
As suggested by Dmitri Bouianov on Coursera discussion forum, this also works:
Y = eye(num_labels)(y, :);
This solution uses elements of y to as indices to select rows from an identity matrix.
In Octave (at least as of 3.6.3, not sure when it was introduced), you can use broadcasting to do this extremely easily. It works like this:
Y = y==1:3
(if y is a row matrix, you need to transpose it first - if you want to have Y transposed instead, use y==(1:3)')

How can I generate the following matrix in MATLAB?

I want to generate a matrix that is "stairsteppy" from a vector.
Example input vector: [8 12 17]
Example output matrix:
[1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1]
Is there an easier (or built-in) way to do this than the following?:
function M = stairstep(v)
M = zeros(length(v),max(v));
v2 = [0 v];
for i = 1:length(v)
M(i,(v2(i)+1):v2(i+1)) = 1;
end
You can do this via indexing.
A = eye(3);
B = A(:,[zeros(1,8)+1, zeros(1,4)+2, zeros(1,5)+3])
Here's a solution without explicit loops:
function M = stairstep(v)
L = length(v); % M will be
V = max(v); % an L x V matrix
M = zeros(L, V);
% create indices to set to one
idx = zeros(1, V);
idx(v + 1) = 1;
idx = cumsum(idx) + 1;
idx = sub2ind(size(M), idx(1:V), 1:V);
% update the output matrix
M(idx) = 1;
EDIT: fixed bug :p
There's no built-in function I know of to do this, but here's one vectorized solution:
v = [8 12 17];
N = numel(v);
M = zeros(N,max(v));
M([0 v(1:N-1)]*N+(1:N)) = 1;
M(v(1:N-1)*N+(1:N-1)) = -1;
M = cumsum(M,2);
EDIT: I like the idea that Jonas had to use BLKDIAG. I couldn't help playing with the idea a bit until I shortened it further (using MAT2CELL instead of ARRAYFUN):
C = mat2cell(ones(1,max(v)),1,diff([0 v]));
M = blkdiag(C{:});
A very short version of a vectorized solution
function out = stairstep(v)
% create lists of ones
oneCell = arrayfun(#(x)ones(1,x),diff([0,v]),'UniformOutput',false);
% create output
out = blkdiag(oneCell{:});
You can use ones to define the places where you have 1's:
http://www.mathworks.com/help/techdoc/ref/ones.html