Upsample vector by including zeros in-between elements - arrays

I am trying to make a Upsampling code, so i want to insert a zeros vector inside a vector, like this:
z=[0 0]%Zeros Vector
x=[1 2 3 4]%Vector to Upsample
y=[1 0 0 2 0 0 3 0 0 4 0 0]%Vector Upsampled
I have this code:
fs=20;
N=50;
T=1/fs;
n=0:1:N-1;
L=3;
M=2;
x = exp(-0.5*n*T).*sin(2*pi*n*T);
A=zeros(1,L);
disp(A);
for i = 1:M:length(x)
x(:,i)=A;
end
disp(x);
But I am gettinf this error:
A(I,J,...) = X: dimensions mismatch
Any Idea of how can I do that?

Forget the loop. Use the following solution:
out = zeros(1,length(x)*L);
out(:,1:L:end) = x

Here's a solution using bsxfun and reshape:
y = reshape(bsxfun(#times,[1;z.'],x),1,[]);
I initially thought of repelem, but decided it was too much work. However, if you just want to make your vector longer using a "zero order approximation" - this is just the function for you.

You can use repmat and reshape to get the upsampled vector as:
y = reshape([x' repmat(z,size(x,2),1)]',1,[])
y =
1 0 0 2 0 0 3 0 0 4 0 0
Keep in mind that z and x are row vectors, you may need to play with the statement a little bit if they are column vectors.

A short alternative using the kronecker tensor product:
y = kron(x,[1, z]) %// x(:).' and z(:).' for independent vector orientations
And another fast alternative:
y = [1; z(:)]*x; y = y(:).' %// x(:).' for independent vector orientations
which is basically equivalent to:
y = reshape( [1; z(:)]*x, 1, []) %// x(:).' for independent vector orientations

Use upsample
fs=20;
N=50;
T=1/fs;
n=0:1:N-1;
L=3;
x = exp(-0.5*n*T).*sin(2*pi*n*T);
x = upsample(x, L)

Related

Forming a 'partial' identity-matrix according to a partially filled vector

I'm currently forming a matrix from a vector in MATLAB following the scheme described below:
Given is a vector x containing ones and zeros in an arbitrary order, e.g.
x = [0 1 1 0 1];
From this, I would like to form a matrix Y that is described as follows:
Y has m rows, where m is the number of ones in x (here: 3).
Each row of Y is filled with a one at the k-th entry, where k is the position of a one in vector x (here: k = 2,3,5)
For the example x from above, this would result in:
Y = [0 1 0 0 0;
0 0 1 0 0;
0 0 0 0 1]
This is identical to an identity matrix, that has its (x=0)th rows eliminated.
I'm currently achieving this via the following code:
x = [0,1,1,0,1]; %example from above
m = sum(x==1);
Y = zeros(m,numel(x));
p = 1;
for n = 1:numel(x)
if x(n) == 1
Y(p,n) = 1;
p = p+1;
end
end
It works but I'm kind of unhappy with it as it seems rather inefficient and inelegant. Any ideas for a smoother implementation, maybe using some matrix multiplications or so are welcome.
Here are a few one-line alternatives:
Using sparse:
Y = full(sparse(1:nnz(x), find(x), 1));
Similar but with accumarray:
Y = accumarray([(1:nnz(x)).' find(x(:))], 1);
Using eye and indexing. This assumes Y is previously undefined:
Y(:,logical(x)) = eye(nnz(x));
Use find to obtain the indices of ones in x which are also the column subscripts of ones in Y. Find the number of rows of Y by adding all the elements of the vector x. Use these to initialise Y as a zero matrix. Now find the linear indices to place 1s using sub2ind. Use these indices to change the elements of Y to 1.
cols = find(x);
noofones = sum(x);
Y = zeros(noofones, size(x,2));
Y(sub2ind(size(Y), 1:noofones, cols)) = 1;
Here's an alternative using matrix multiplications:
x = [0,1,1,0,1];
I = eye(numel(x));
% construct identity matrix with zero rows
Y = I .* x; % uses implicit expansion from 2016b or later
Y = Y(logical(x), :); % take only non-zero rows of Y
Result:
Y =
0 1 0 0 0
0 0 1 0 0
0 0 0 0 1
Thanks to #SardarUsama's comment for simplifying the code a bit.
Thanks everybody for the nice alternatives! I tried out all your solutions and averaged execution times over 1e4 executions for random (1000-entry) x-vectors. Here are the results:
(7.3e-4 sec) full(sparse(1:nnz(x), find(x), 1));
(7.5e-4 sec) cols = find(x);
noofones = sum(x);
Y = zeros(noofones, size(x,2));
Y(sub2ind(size(Y), 1:noofones, cols)) = 1;
(7.7e-4 sec) Y = accumarray([(1:nnz(x)).' find(x(:))], 1);
(1.7e-3 sec) I = speye(numel(x));
Y = I .* x;
Y = full(Y(logical(x), :));
(3.1e-3 sec) Y(:,logical(x)) = eye(nnz(x));
From your comment "This is identical to an identity matrix, that has its (x=0)th rows eliminated.", well, you can also explicitly generate it as such:
Y = eye(length(x));
Y(x==0, :) = [];
Very slow option for long x, but it works slightly faster than full(sparse(... for x with 10 elements on my computer.

Matlab Convert Vector to Binary Matrix [duplicate]

This question already has answers here:
Create a zero-filled 2D array with ones at positions indexed by a vector
(4 answers)
Closed 6 years ago.
I have a vector v of size (m,1) whose elements are integers picked from 1:n. I want to create a matrix M of size (m,n) whose elements M(i,j) are 1 if v(i) = j, and are 0 otherwise. I do not want to use loops, and would like to implement this as a simple vector-matrix manipulation only.
So I thought first, to create a matrix with repeated elements
M = v * ones(1,n) % this is a (m,n) matrix of repeated v
For example v=[1,1,3,2]'
m = 4 and n = 3
M =
1 1 1
1 1 1
3 3 3
2 2 2
then I need to create a comparison vector c of size (1,n)
c = 1:n
1 2 3
Then I need to perform a series of logical comparisons
M(1,:)==c % this results in [1,0,0]
.
M(4,:)==c % this results in [0,1,0]
However, I thought it should be possible to perform the last steps of going through each single row in compact matrix notation, but I'm stumped and not knowledgeable enough about indexing.
The end result should be
M =
1 0 0
1 0 0
0 0 1
0 1 0
A very simple call to bsxfun will do the trick:
>> n = 3;
>> v = [1,1,3,2].';
>> M = bsxfun(#eq, v, 1:n)
M =
1 0 0
1 0 0
0 0 1
0 1 0
How the code works is actually quite simple. bsxfun is what is known as the Binary Singleton EXpansion function. What this does is that you provide two arrays / matrices of any size, as long as they are broadcastable. This means that they need to be able to expand in size so that both of them equal in size. In this case, v is your vector of interest and is the first parameter - note that it's transposed. The second parameter is a vector from 1 up to n. What will happen now is the column vector v gets replicated / expands for as many values as there are n and the second vector gets replicated for as many rows as there are in v. We then do an eq / equals operator between these two arrays. This expanded matrix in effect has all 1s in the first column, all 2s in the second column, up until n. By doing an eq between these two matrices, you are in effect determining which values in v are equal to the respective column index.
Here is a detailed time test and breakdown of each function. I placed each implementation into a separate function and I also let n=max(v) so that Luis's first code will work. I used timeit to time each function:
function timing_binary
n = 10000;
v = randi(1000,n,1);
m = numel(v);
function luis_func()
M1 = full(sparse(1:m,v,1));
end
function luis_func2()
%m = numel(v);
%n = 3; %// or compute n automatically as n = max(v);
M2 = zeros(m, n);
M2((1:m).' + (v-1)*m) = 1;
end
function ray_func()
M3 = bsxfun(#eq, v, 1:n);
end
function op_func()
M4= ones(1,m)'*[1:n] == v * ones(1,n);
end
t1 = timeit(#luis_func);
t2 = timeit(#luis_func2);
t3 = timeit(#ray_func);
t4 = timeit(#op_func);
fprintf('Luis Mendo - Sparse: %f\n', t1);
fprintf('Luis Mendo - Indexing: %f\n', t2);
fprintf('rayryeng - bsxfun: %f\n', t3);
fprintf('OP: %f\n', t4);
end
This test assumes n = 10000 and the vector v is a 10000 x 1 vector of randomly distributed integers from 1 up to 1000. BTW, I had to modify Luis's second function so that the indexing will work as the addition requires vectors of compatible dimensions.
Running this code, we get:
>> timing_binary
Luis Mendo - Sparse: 0.015086
Luis Mendo - Indexing: 0.327993
rayryeng - bsxfun: 0.040672
OP: 0.841827
Luis Mendo's sparse code wins (as I expected), followed by bsxfun, followed by indexing and followed by your proposed approach using matrix operations. The timings are in seconds.
Assuming n equals max(v), you can use sparse:
v = [1,1,3,2];
M = full(sparse(1:numel(v),v,1));
What sparse does is build a sparse matrix using the first argument as row indices, the second as column indices, and the third as matrix values. This is then converted into a full matrix with full.
Another approach is to define the matrix containing initially zeros and then use linear indexing to fill in the ones:
v = [1,1,3,2];
m = numel(v);
n = 3; %// or compute n automatically as n = max(v);
M = zeros(m, n);
M((1:m) + (v-1)*m) = 1;
I think I've also found a way to do it, and it would be nice if somebody could tell me which of the methods shown is faster for very large vectors and matrices. The additional method I thought of is the following
M= ones(1,m)'*[1:n] == v * ones(1,n)

Array inside array in MATLAB

If n=4 for example, How to create an array like this in MATLAB?
[[0] [0 0] [0 0 0] [0 0 0 0]]
Is there a way to create an array inside a for loop, for example ?
This is what I want to achieve (I know it's wrong code):
for i=1:n
table(i)=zeros(i);
end
You need a cell array to hold your numeric vectors. Cell arrays are used in Matlab when the contents of each cell are of different size or type.
Additional comments:
I'm renaming your variable i to k, to avoid shadowing the imaginary unit.
I'm also renaming your variable table to t, to avoid shadowing the table function.
zeros(k) gives a kxk matrix of zeros. To obtain a row vector of zeros use zeros(1,k).
It's better to preallocate the cell array to improve speed.
Taking the above into account, the code is:
n = 4;
t = cell(1,n); %// preallocate: 1xn cell array of empty cells
for k = 1:n
t{k} = zeros(1,k);
end
This gives:
>> celldisp(t)
t{1} =
0
t{2} =
0 0
t{3} =
0 0 0
t{4} =
0 0 0 0
Equivalently, you could replace the for loop by the more compact arrayfun:
result = arrayfun(#(k) zeros(1,k), 1:n, 'uniformoutput', false);

Creating Indicator Matrix

For a vector V of size n x 1, I would like to create binary indicator matrix M of the size n x Max(V) such that the row entries of M have 1 in the corresponding columns index, 0 otherwise.
For eg: If V is
V = [ 3
2
1
4]
The indicator matrix should be
M= [ 0 0 1 0
0 1 0 0
1 0 0 0
0 0 0 1]
The thing about an indicator matrix like this, is it is better if you make it sparse. You will almost always be doing a matrix multiply with it anyway, so make that multiply an efficient one.
n = 4;
V = [3;2;1;4];
M = sparse(V,1:n,1,n,n);
M =
(3,1) 1
(2,2) 1
(1,3) 1
(4,4) 1
If you insist on M being a full matrix, then making it so is simple after the fact, by use of full.
full(M)
ans =
0 0 1 0
0 1 0 0
1 0 0 0
0 0 0 1
Learn how to use sparse matrices. You will gain greatly from doing so. Admittedly, for a 4x4 matrix, sparse will not gain by much. But the example cases are never your true problem. Suppose that n was really 2000?
n = 2000;
V = randperm(n);
M = sparse(V,1:n,1,n,n);
FM = full(M);
whos FM M
Name Size Bytes Class Attributes
FM 2000x2000 32000000 double
M 2000x2000 48008 double sparse
Sparse matrices do not gain only in terms of memory used. Compare the time required for a single matrix multiply.
A = magic(2000);
tic,B = A*M;toc
Elapsed time is 0.012803 seconds.
tic,B = A*FM;toc
Elapsed time is 0.560671 seconds.
a quick way to do this - if you do not require sparse matrix - is to create an identity matrix, of size at least the max(v), then to create your indicator matrix by extracting indexes from v:
m = max(V);
I = eye(m);
V = I(V, :);
You would like to create the Index matrix to be sparse for memory sake. It is as easy as:
vSize = size(V);
Index = sparse(vSize(1),max(V));
for i = 1:vSize(1)
Index(i, v(i)) = 1;
end
I've used this myself, enjoy :)
You can simply combine the column index in V with a row index to create a linear index, then use that to fill M (initialized to zeroes):
M = zeros(numel(V), max(V));
M((1:numel(V))+(V.'-1).*numel(V)) = 1;
Here's another approach, similar to sparse but with accumarray:
V = [3; 2; 1; 4];
M = accumarray([(1:numel(V)).' V], 1);
M=sparse(V,1:size(V,1),1)';
will produce a sparse matrix that you can use in calculations as a full version.
You could use full(M) to "inflate" M to actually store zeros.

How can I efficiently remove zeroes from a (non-sparse) matrix?

I have a matrix:
x = [0 0 0 1 1 0 5 0 7 0];
I need to remove all of the zeroes, like so:
x = [1 1 5 7];
The matrices I am using are large (1x15000) and I need to do this multiple times (5000+), so efficiency is key!
One way:
x(x == 0) = [];
A note on timing:
As mentioned by woodchips, this method seems slow compared to the one used by KitsuneYMG. This has also been noted by Loren in one of her MathWorks blog posts. Since you mentioned having to do this thousands of times, you may notice a difference, in which case I would try x = x(x~=0); first.
WARNING: Beware if you are using non-integer numbers. If, for example, you have a very small number that you would like to consider close enough to zero so that it will be removed, the above code won't remove it. Only exact zeroes are removed. The following will help you also remove numbers "close enough" to zero:
tolerance = 0.0001; % Choose a threshold for "close enough to zero"
x(abs(x) <= tolerance) = [];
Just to be different:
x=x(x~=0);
or
x=x(abs(x)>threshold);
This has the bonus of working on complex numbers too
Those are the three common solutions. It helps to see the difference.
x = round(rand(1,15000));
y = x;
tic,y(y==0) = [];toc
Elapsed time is 0.004398 seconds.
y = x;
tic,y = y(y~=0);toc
Elapsed time is 0.001759 seconds.
y = x;
tic,y = y(find(y));toc
Elapsed time is 0.003579 seconds.
As you should see, the cheapest way is the direct logical index, selecting out the elements to be retained. The find is more expensive, since matlab finds those elements, returning a list of them, and then indexes into the vector.
Here's another way
y = x(find(x))
I'll leave it to you to figure out the relative efficiency of the various approaches you try -- do write and let us all know.
Though my timing results are not conclusive to whether it is significantly faster, this seems to be the fastest and easiest approach:
y = nonzeros(y)
x = [0 0 0 1 1 0 5 0 7 0]
y = [0 2 0 1 1 2 5 2 7 0]
Then x2 and y2 can be obtained as:
x2=x(~(x==0 & y==0))
y2=y(~(x==0 & y==0))
x2 = [0 1 1 0 5 0 7]
y2 = [2 1 1 2 5 2 7]
Hope this helps!

Resources