Matlab: Can I create a matrix with unknown number of dimensions? - matlab

Normally a matrix has 2 dimensions, but there doesn't seem to be a limit on the number of dimensions a matrix may have in MATLAB.
To create a 4-dimensional matrix, for example, I can do this:
>> x = zeros(2,2,2,2)
x(:,:,1,1) =
0 0
0 0
x(:,:,2,1) =
0 0
0 0
x(:,:,1,2) =
0 0
0 0
x(:,:,2,2) =
0 0
0 0
Is there a way to create a matrix of which the number of dimensions is only known at runtime?

You could call zeros like this:
x = zeros([2 2 2 2])
Hence, you can customize the input array as you want.
For example: to create a 2x2x2x2x2 matrix (where D = 5, the number of dimensions):
D = 5;
x = zeros(zeros(1, D) + 2)

Rafael's answer hits the nail on the head. But there's also a general way to do this sort of thing even when the function doesn't have an overload for something like a vector input as in the case of zeros. You can use a cell array like so:
>> dims = {2,2,2,2};
>> zeros(dims{:})
ans(:,:,1,1) =
0 0
0 0
ans(:,:,2,1) =
0 0
0 0
ans(:,:,1,2) =
0 0
0 0
ans(:,:,2,2) =
0 0
0 0
I've found this approach to be very useful for other functions.
Edit:
This approach is more robust. Here's another example:
imginfo = { rand(40), [0 1], 'Colormap', colormap(jet) };
figure, imshow(a{:});

Related

How can I create a modified identity matrix?

I have an identity matrix in MATLAB which is used in some regression analysis for joint hypothesis tests. However, when I change the linear restrictions for my tests, I can no longer rely on the identity matrix.
To give a simple example, here is some code which produces an identity matrix depending on the value of y:
for i = [1, 2, 4]
y = i
x = 5;
H = eye(y*x)
end
However, what I need is not the identity matrix, but the first two rows and all others to be zero.
For the first example, the code produces an eye(5):
H =
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
I need something that given y does not produce the identity but in fact produces:
H =
1 0 0 0 0
0 1 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
Can I adjust the identity matrix to include zeroes only after the first two rows?
I think the simplest solution is to make a matrix of all zeroes and then just place the two ones by linear indexing:
H = zeros(x*y);
H([1 x*y+2]) = 1;
Generalizing the above to putting the first N ones along the diagonal:
H = zeros(x*y);
H(x*y.*(0:(N-1))+(1:N)) = 1;
As suggested in this comment you can use diag:
diag([ones(2,1); zeros(x*y-2,1)])
This works because diag makes a vector become the main diagonal of a square matrix, so you can simply feed it the diagonal vector, which is your case would be 2 1s and the rest 0s.
Of course if you need a variable amount of 1s, which I was in doubt about hence the comment,
n=2;
diag([ones(n,1); zeros(x*y-n,1)])
Here are some alternatives:
Use blkdiag to diagonally concatenate an identity matrix and a zero matrix:
y = 5; x = 2;
H = blkdiag(eye(x), zeros(y-x));
A more exotic approach is to use element-wise comparisons with singleton expansion and exploit the fact that two NaN's are not equal to each other:
y = 5; x = 2;
H = [1:x NaN(1,y-x)];
H = double(bsxfun(#eq, H, H.'))

How to make an array of matrix (of varying sizes)

I'm trying to get to grips with matlab, so this question is more about syntax than anything else.
I want to create a vector (1xn) of matrices. The matrices are all possibly of different dimensions eg. matrix 1 = 4 x 5, matrix 2 = 5 x 6 etc.
I tried using a for loop, but I had the following error:
Subscripted assignment dimension mismatch.
You can store an array of matrices of different sizes as a cell array of matrices. Often you'll want to create these cell arrays dynamically using the arrayfun function which will do this for you if you set the UniformOutput option to 0.
Example:
cols = [4 5 6];
rows = [1 2 3];
A = arrayfun(#(i) zeros(rows(i),cols(i)),1:3,'UniformOutput',0);
A{:}
Outputs:
ans =
0 0 0 0
ans =
0 0 0 0 0
0 0 0 0 0
ans =
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0

Plot the density of a matrix

Good day,
In Matlab I have got a matrix which is very sparse. Now I would like to plot the 'density' of the matrix. Let's say I have a matrix A:
A = [3 0 0
0 2 0
0 0 1];
Now the plot should look something like:
x
x
x
So there should be a dot (or something else) at each location (row, column) in which matrix A has got a nonzero value.
Any ideas?
spy is what you need:
% taken from MatLab documentation
B = bucky;
spy(B)
Consider something like this:
subs = zeros(0,2);
for ind = [find(A)']
[r,c] = ind2sub(size(A), ind);
subs = [subs; [r,c]];
end
scatter(subs(:,2), subs(:,1));
set(gca,'YDir','Reverse')
xlim([1 size(A,2)])
ylim([1 size(A,1)])
Which, for the matrix A:
0 1 0 1 1
0 0 0 0 0
0 1 0 0 0
0 1 0 1 1
0 0 1 1 0
Gives you the following scatter plot:
What about this :
A=[3 0 0; 0 2 0; 0 0 1];
imagesc(A)

Inserting variable number of zeros between non-zero elements in a vector in MATLAB

I have a vector like:
a = [1,2,3,4,5,6...,n]
and I would like to obtain a new vector like this:
a_new = [1,0,0,2,0,0,3,0,0,4,0,0,5,0,0,6,...,0,0,n]
where a fixed number of zeros (2 in the above example) are inserted between the non-zero elements. If I choose zero_p=3, the new vector would be:
a_new = [1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,6,...,0,0,0,n]
etc.
How can I do this?
Try this:
zero_p=3;
a_new=zeros(1, (zero_p+1)*length(a)-zero_p);
a_new(1:(zero_p+1):end)=a;
(Untested, but should hopefully work.)
There's a few ways I can think of:
Kronecker product
The kronecker product is excellently suited for this.
In Matlab, kron is what you're looking for:
a = 1:4;
a = kron(a, [1 0 0])
ans =
1 0 0 2 0 0 3 0 0 4 0 0
or, generalized,
a = 1:4;
zero_p = 3;
b = [1 zeros(1,zero_p-1)];
a = kron(a, b)
ans =
1 0 0 2 0 0 3 0 0 4 0 0
If you want to have it end with a non-zero element, you have to do one additional step:
a = a(1:end-zero_p);
Or, if you like one-liners, the whole thing can be done like this:
a = 1:4;
zero_p = 3;
a = [kron(a(1:end-1), [1 zeros(1,zero_p-1)]), a(end)]
ans =
1 0 0 2 0 0 3 0 0 4
Zero padding
Probably the simplest method and best performance:
a = 1:4;
zero_p = 3;
a = [a; zeros(zero_p, size(a, 2))];
a = a(1:end-zero_p);
Matrix multiplication
Also simple, readable and great performance, although it might be overkill for many situations other than this particular scenario:
a = 1:4;
b = [1; zeros(zero_p, 1)];
a = b*a;
a = a(1:end-zero_p);
x = [1 2 3 4 5];
upsample(x,3)
o/p: 1 0 0 2 0 0 3 0 0 4 0 0 5 0 0
Cheers!!

MATLAB Expanding A Matrix with Zeros

I need a matrix of nxn, where the first pxp of it contains ones and rest are zeros. I can do it with traversing the cells, so I'm not asking a way to do it. I'm looking for "the MATLAB way" to do it, using built-in functions and avoiding loops etc.
To be more clear;
let n=4 and p=2,
then the expected result is:
1 1 0 0
1 1 0 0
0 0 0 0
0 0 0 0
There are possibly more than one elegant solution to do it, so I will accept the answer with the shortest and most readable one.
P.S. The question title looks a bit irrelevant: I put that title because my initial approach would be creating a pxp matrix with ones, then expanding it to nxn with zeros.
The answer is creating a matrix of zeroes, and then setting part of it to 1 using indexing:
For example:
n = 4;
p = 2;
x = zeros(n,n);
x(1:p,1:p) = 1;
If you insist on expanding, you can use:
padarray( zeros(p,p)+1 , [n-p n-p], 0, 'post')
Another way to expand the matrix with zeros:
>> p = 2; n = 4;
>> M = ones(p,p)
M =
1 1
1 1
>> M(n,n) = 0
M =
1 1 0 0
1 1 0 0
0 0 0 0
0 0 0 0
You can create the matrix easily by concatenating horizontally and vertically:
n = 4;
p = 2;
MyMatrix = [ ones(p), zeros(p, n-p); zeros(n-p, n) ];
>> p = 2; n = 4;
>> a = [ones(p, 1); zeros(n - p, 1)]
a =
1
1
0
0
>> A = a * a'
A =
1 1 0 0
1 1 0 0
0 0 0 0
0 0 0 0