Array inside array in MATLAB - arrays

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);

Related

R: create an array of matrices from a list

I am trying to create an array from matrices. The matrices are all of identical dimensions (NxN). I have every matrix in a single csv file without header. Data are tab delimited.
In other threads it was suggested to do it as follows:
temp = list.files(pattern="*.csv")
named.list <- lapply(temp, read.csv,header=FALSE, sep = "")
arr <- abind(named.list)
However, this does not create what I want. This creates a 2-dimenaional Nx(N*k) data frame (where N = columns/rows and k = number of matrices).
So in my case I have 5 matrices, 40 columns and 40 rows each. Using abind creates a [1:40, 1:200] data frame.
> str(arr)
int [1:40, 1:200] 0 1 0 0 0 0 0 0 0 0 ...
- attr(*, "dimnames")=List of 2
..$ : NULL
..$ : chr [1:200] "V1" "V2" "V3" "V4" ...
What I want is a [1:40, 1:40, 1:5] three-dimensional array of matrices:
> str(z)
int [1:40, 1:40, 1:5] 0 1 0 0 0 0 0 0 0 0 ...
I think my fundamental problem is that I cannot manage to convert the list of data frames in named.list to a list of matrices.
this worked for me
temp = list.files(pattern="*.csv")
r <- simplify2array(temp)
However, the resulting array had dimensions [nrow, ncol, n] where the first two elements are matrix dimensions and the last is the number of matrices stored in r. My specific analysis required [n, nrow, ncol] to achieve this change I used the aperm function as follows r <- aperm(r, c(3,1,2)) based on this answer function from base package that is a generalization of the transpose t() function
I solved it, the "abind" got me close. The following line was missing:
arr2<-array(arr,dim= c(40,40,5))
This gives me:
str(arr2)
int [1:40, 1:40, 1:5] 0 1 0 0 0 0 0 0 0 0 ...
abind is the way to go. If rbindlist was used beforehand, the structure of the individual data sets gets messed up.
You can use:
library(data.table)
arr <- rbindlist(named.list ,use.names = T,fill = T);

Upsample vector by including zeros in-between elements

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)

Vectorizing addition of subarray

Let's say I have two (large) vectors a=[0 0 0 0 0] and b=[1 2 3 4 5] of the same size and one index vector ind=[1 5 2 1] with values in {1,...,length(a)}. I would like to compute
for k = 1:length(ind)
a(ind(k)) = a(ind(k)) + b(ind(k));
end
% a = [2 2 0 0 5]
That is, I want to add those entries of b declared in ind to a including multiplicity.
a(ind)=a(ind)+b(ind);
% a = [1 2 0 0 5]
is much faster, of course, but ignores indices which appear multiple times.
How can I speed up the above code?
We can use unique to identify the unique index values and use the third output to determine which elements of ind share the same index. We can then use accumarray to sum all the elements of b which share the same index. We then add these to the original value of a at these locations.
[uniqueinds, ~, inds] = unique(ind);
a(uniqueinds) = a(uniqueinds) + accumarray(inds, b(ind)).';
If max(inds) == numel(a) then this could be simplified to the following since accumarray will simply return 0 for any missing entry in ind.
a(:) = a(:) + accumarray(ind(:), b(ind));
Another approach based on accumarray:
a(:) = a(:) + accumarray(ind(:), b(ind(:)), [numel(a) 1]);
How it works
accumarray with two column vectors as inputs aggregates the values of the second input corresponding to the same index in the first. The third input is used here to force the result to be the same size as a, padding with zeros if needed.

Converting all elements in a 2D Logical array into "Zero" except elements whose coordinates are given in another array

I'm working with a 2D Logical array and i need to make all its elements zero, except some elements whose indices are randomly given in another 2D double array. By randomly i mean that the rows no. and cols no. are not in sequence.
consider:
A=[1 0 0; 0 1 1; 1 1 0]; %The logical array
I=[3 1; 2 3]; % indices of the elements i want them unchanged(stay 1)
final_A=[0 0 0; 0 0 1; 1 0 0]; % expected output
Any help?
You really just need a matrix the size of A where the elements in I are set to true and all others are set to false. You can use sub2ind to convert from the row/column specified in I to absolute indices.
final_A = false(size(A));
final_A(sub2ind(size(A), I(:,1), I(:,2))) = true;
0 0 0
0 0 1
1 0 0
This assumes that all elements of A specified in I were true to begin with. If this was not the case, then you will want to ensure that only the ones that were initially true in A are kept. You can do this using an element-wise and (&) operation.
final_A = final_A & A;

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.

Resources