Incremental matrix without loop - matlab

(Just approaching Matlab for personal understanding), suppose I have a Z,Y matrix in this case Z=1 Y=3
A=1:3
output: 1 2 3
Now I need to increase the matrix vertically to obtain:
1 2 3
2 4 6
3 6 9
How can I achieve that without using a loop?

The easiest way is to use vector multiplication.
If your goal is to obtain
1 2 3
2 4 6
3 6 9
given A=1:3
all you have to do is
A.'*A
This will take the vector product of the transpose (.') of A with A itself

Another way is to use bsxfun:
A = [1 2 3];
B = bsxfun(#times, A.', A);
This is essentially the same answer as Federico's where the outer product of the vector is taken.

Related

Convert column matrix to multiple rows with duplicated data

In Matlab, given matrix 'a' as:
a = [1 2 3 4 5 6 7 8 9]';
but a few million rows deep, what would be the best way to convert it to the format shown in 'b'?
b = [1 2 3 4 5 6
2 3 4 5 6 7
3 4 5 6 7 8
4 5 6 7 8 9]
where each row in 'b' contains N consecutive values from 'a'?
I can write a function but was wondering if there's a faster, more built-in way?
Another option is the built-in Hankel matrix, for example in your case:
hankel(1:4,4:9)
or in the general case for a vector a and block size N
hankel(a(1:N),a(N:numel(a)))
I have no idea if the implementation of hankel is better or worse than #Luis Mendo solution, so test and see which solution is better for you...
Let
a = [1 2 3 4 5 6 7 8 9].'; % data
N = 4; % block size
If you have the Image Processing Toolbox: use im2col with the 'sliding' option:
b = im2col(a(:), [N 1], 'sliding');
Or, without any toolbox: use implict expansion (or bsxfun) to create the appropriate indexing matrix:
b = a((1:numel(a)-N+1)+(0:N-1).');

Reshape a matrix by splitting it after k columns in MATLAB

Suppose that I have a matrix , let's call it A, as follows:
1 2 3 4 5 1 2 3 4 5
0 2 4 6 8 1 3 5 7 9
And I want to reshape it into a matrix like this:
1 2 3 4 5
0 2 4 6 8
1 2 3 4 5
1 3 5 7 9
So, basically, what I want to be done is that MATLAB first reads a block of size (2,5) and then splits the remaining matrix to the next row and then repeats this so on so forth until we get something like in my example.
I tried to do this using MATLAB's reshape command in several ways but I failed. Any help is appreciated. In case that it matters, my original data is larger. It's (2,1080). Thanks.
I don't believe you can do this in a single command, but perhaps someone will correct me. If speed isn't a huge concern a for loop should work fine.
Alternatively you can get your results by reshaping each row of A and then placing the results into every other row of a new matrix. This will also work with your larger data.
A = [1 2 3 4 5 1 2 3 4 5
0 2 4 6 8 1 3 5 7 9];
An = zeros(numel(A)/5, 5); % Set up new, empty matrix
An(1:2:end,:) = reshape(A(1,:), 5, [])'; % Write the first row of A to every other row of An
An(2:2:end,:) = reshape(A(2,:), 5, [])' % Write second row of A to remaining rows
An =
1 2 3 4 5
0 2 4 6 8
1 2 3 4 5
1 3 5 7 9
You may need to read more about indexing in the Matlab's documentation.
For your example, it is easy to do the following
A=[1 2 3 4 5 1 2 3 4 5; 0 2 4 6 8 1 3 5 7 9]
a1=A(:,1:5); % extract all rows, and columns from 1 to 5
a2=A(:,6:end); % extract all rows, and columns from 6 to end
B=[a1;a2] % construct a new matrix.
It is not difficult to build some sort of loops to extract the rest.
Here's a way you can do it in one line using the reshape and permute commands:
B = reshape(permute(reshape(A,2,5,[]), [1,3,2]), [], 5);
The reshape(A,2,5,[]) command reshapes your A matrix into a three-dimensional tensor of dimension 2 x 5 x nblocks, where nblocks is the number of blocks in A in the horizontal direction. The permute command then swaps the 2nd and 3rd dimensions of this 3D tensor, so that it becomes a 2 x nblocks x 5 tensor. The final reshape command then transforms the 3D tensor into a matrix of dimension (2*nblocks) x 5.
Looking at the results at each stage may give you a better idea of what's happening.

Removing third dimension of matrix

Lets say I have matrix such that A(:,:,1)=[1,2,3;2,3,4], A(:,:,2)=[3,4,5;4,5,6].
How is the easiest way of accessing and plotting the vectors (1,2,3),(2,3,4),(3,4,5),(4,5,6). I tried creating B=[A(:,:,1);A(:,:,2)], but i need a procedure to arbitrary number of A's.
Hope this isn't trivial and I've formulated myself satisfactory.
You should think 'vertically'. This will allow you to use colon indexing:
>> A(:,:,1) = [1,2,3;2,3,4].'; %'// NOTE: transpose of your original
>> A(:,:,2) = [3,4,5;4,5,6].'; %'// NOTE: transpose of your original
>> A(:,:)
ans =
1 2 3 4
2 3 4 5
3 4 5 6
The colon indexing with two colons works for any dimension A:
>> A(:,:,:,:,1,1) = [1 2 3; 2 3 4].'; %'
>> A(:,:,:,:,2,1) = [3 4 5; 4 5 6].'; %'
>> A(:,:,:,:,1,2) = [5 6 7; 6 7 8].'; %'
>> A(:,:,:,:,2,2) = [7 8 9; 8 9 0].'; %'
>> A(:,:)
ans =
1 2 3 4 5 6 7 8
2 3 4 5 6 7 8 9
3 4 5 6 7 8 9 0
Colon indexing in MATLAB is quite interesting and really powerful once you master it. For example, if you use fewer colons than there are dimensions in the array (like above), MATLAB will automatically concatenate the remainder of the data along the dimension equal to the colon count.
So, if A has 48 dimensions, but you index with just 2 colons: you'll get a 2D array, that is the concatenation of the remaining 46 dimensions along the 2nd dimension.
In general: if A has N dimensions, but you index with just M ≤ N colons: you'll get an M-D array, that is the concatenation of the remaining N-M dimensions along the Mth dimension.
So as long as you are free to define your A to contain vectors on the columns rather than the rows (you should advise everyone to do this, as virtually everything in MATLAB is a bit faster that way), I think this is the fastest and most elegant way to do what you want.
If not, well, then just reshape like Dan :)
Assuming the order does not matter, here is how you can do it for vectors of length 3:
B = reshape(shiftdim(A,2), [], 3)
plot(B')
For vectors of arbitrary dimensions, replace 3 by size(A,2)

Duplicate the first row and the first column of a matrix

I have a 3*3 matrix A
A = [1 2 3
4 5 6
7 8 9];
I want to duplicate only the first row and column of this matrix. It should look like
1 1 2 3
1 1 2 3
4 4 5 6
7 7 8 9
can someone tell how can i do this in matlab
I think this is a good way just using indexing
A([1, 1:end], [1, 1:end])
You can do that by concatenating different parts of the original matrix:
B=[A(1) A(1,:);A(:,1) A];
In this expression A(1) is the top left element of A, A(1,:) is the first row and A(:,1) is the first column.
See the documentation on the colon operator.
In the code below, A is your starting point and I believe E is what you want to achieve.
You can of course combine all the intermediate expressions to achieve the final result in one step.
A= [1 2 3; 4 5 6; 7 8 9]
B= A(1:3,1:1)
C= [B A]
D= C(1:1,1:4)
E= [D;C]
A bit late in the game, but worthwhile answering. You can use padarray for that :
B = padarray(A,[1 1],'replicate','pre')
It's a one liner and more generic if you want to add more than just a single first and column ...

Reconstruct matrix from diagonals in matlab

Given a vector of the counter-diagonals of a matrix in matlab, is there an easy way to reconstruct the matrix?
For example, given
x = [1 2 3 4 5 6 7 8 9]
is there any easy way to reconstruct it to the following?
1 2 4
3 5 7
6 8 9
This is made slightly easier by the fact that the dimensions of the original block are known. Reconstructing a rotation or transposition of the original matrix is fine, since rotating and transposing are easy to undo. Faster is better, this calculation has to be done on many xs.
Thanks!
You can create the corresponding Hankel matrix and use it for sorting (works only if the output is a square matrix!):
x = [1 2 3 4 5 6 7 8 9];
%# find size of output (works only with square arrays)
n=sqrt(length(x));
%# create Hankel matrix
hh = hankel(1:n,n:(2*n-1));
%# sort to get order of elements (conveniently, sort doesn't disturb ties)
[~,sortIdx]=sort(hh(:));
%# reshape and transpose
out = reshape(x(sortIdx),n,n)'; %'# SO formatting
out =
1 2 4
3 5 7
6 8 9