Reshape and rearrange array - arrays

I have a large array, which looks like this:
1
4
5
3
6
2
7
4
3
I want to rearrange this array that it looks like this:
7 4 3
3 6 2
1 4 5
My original array has the size 13700x1, so I cannot do it manually and if I use the reshape function, the array gets shaped in the wrong way:
1 3 7
4 6 4
5 2 3
I hope my intention is clear. Thanks!

Try
tmpArray = [1
4
5
3
6
2
7
4
3]
flipud(reshape(tmpArray, 3, 3).')

x = [1,4,5,3,6,2,7,4,3]';
A = flipud(reshape(x,3,3)');

The other answers assume your vector contains a square number of elements, 4, 9, 16 .... This is true for the example vector, but not for the one you're actually working with (it's 13700x1 according to the question).
This means that the flipud(reshape()) approach will give an error:
Product of known dimensions, 3, not divisible into total number of
elements, 13924.
This is not a problem if you don't want a square matrix, as numbers that can be represented as a product of any of the numbers: 2, 5, 137.
If you want a square matrix, you need to pad the vector with zeros, NaNs or something else. This can be done the following way:
A = randi(100,13700,1); %% Random 13700x1 matrix
n = numel(A); %% Number of elements in A (13700 in this case)
elements = ceil(sqrt(n))^2; %% Number of elements needed in order to make a square matrix
B = [A; zeros(elements-n,1)]; %% Pad the vectors with zeros.
%% You can also d0 B = [A; nan(elements-n,1)];
final_matrix = flipud(reshape(B, sqrt(elements),[]).'); %% Final operation

Related

MATLAB - Get every N elements in a vector

I have an array
a = [1 2 3 4 5 6 7 8]
I want to get every group of 4
so the result is as such
[1 2 3 4]
[5 6 7 8]
I do not know how many elements there will be but I know it is divisible by 4
so something like a(1:4) and a(5:8) wont work, I can use a loop, but is there a way to not use a loop?
For an unknown number of elements in a you can use reshape you just need to figure out how many rows you will have in the final matrix or (better for your case) the number of columns.
a = 1:4*10;
a2 = reshape(a, 4, []).';
If you went the rows routine you would do this.
a = 1:4*10;
a2 = reshape(a, [], numel(a) / 4).';
You just need to be sure that a has the proper number of elements. numel simply tells you the total element count.

average operation in the first 2 of 3 dimensions of a matrix

Suppose A is a 3-D matrix as below (2 rows-2 columns-2 pages).
A(:,:,1)=[1,2;3,4];
A(:,:,2)=[5,6;7,8];
I want to have a vector, say "a", whose inputs are the average of diagonal elements of matrices on each page. So in this simple case, a=[(1+4)/2;(5+8)/2].
But I have difficulties in matlab to do so. I tried the codes below but failed.
mean(A(1,1,:),A(2,2,:))
You can use "partially linear indexing" in the two dimensions that define the diagonal, as follows:
Since partially linear indexing can only be applied on trailing dimensions, you first need to apply permute to rearrange dimensions, so that the first and second dimensions become second and third.
Now you leave the first dimension untouched, linearly-index the diagonals in the second and third dimensions (which effectly reduces those two dimensions to one), and apply mean along the (combined) second dimension.
Code:
B = permute(A, [3 1 2]); %// step 1: permute
result = mean(B(:,1:size(A,1)+1:size(A,1)*size(A,2)), 2); %// step 2: index and mean
In your example,
A(:,:,1)=[1,2;3,4];
A(:,:,2)=[5,6;7,8];
this gives
result =
2.5000
6.5000
You can use bsxfun for a generic solution -
[m,n,r] = size(A)
mean(A(bsxfun(#plus,[1:n+1:n^2]',[0:r-1]*m*n)),1)
Sample run -
>> A
A(:,:,1) =
8 4 1
7 6 3
1 5 8
A(:,:,2) =
1 7 6
8 5 2
1 2 7
A(:,:,3) =
6 2 8
1 1 6
1 4 5
A(:,:,4) =
8 1 6
1 5 1
9 2 7
>> [m,n,r] = size(A);
>> sum(A(bsxfun(#plus,[1:n+1:n^2]',[0:r-1]*m*n)),1)
ans =
22 13 12 20
>> mean(A(bsxfun(#plus,[1:n+1:n^2]',[0:r-1]*m*n)),1)
ans =
7.3333 4.3333 4 6.6667

Matlab - Multidimensional Arrays Confusion

I have this 4 integer value output
example:
out = [ 8 7 6 5 ]
I would to save these 4 values in one place (in row i column j)
Such that when I try to access
array(i,j) I get the 4 values 8 7 6 5
I'm failing miserably. Any help is appreciated
If the number of values is the same for all i, and j, use a 3D array of size MxNx4:
array(1,1,:) = [8 7 6 5];
array(1,2,:) = [11 12 13 14];
You could imagine the four numbers are stacked on top of each other along a "depth" dimension in row i and column j.
array(i,j,:) gives the 1x1x4 array containing the four numbers corresponding to i, j. When accesing each group of four numbers, you may want to use squeeze to remove the singleton dimensions, i.e. to obtain the result as a column vector:
>> squeeze(array(1,1,:))
ans =
8
7
6
5
If the number of values may be different for each i and j, use a 2D cell array:
array{1,1} = [8 7 6 5];
array{1,2} = [11 12];
So array{i,j} gives the vector:
>> array{1,1}
ans =
8 7 6 5

Compare Values in Array on Specific Indexes in Matlab

how to Compare Values in Array on Specific Indexes in Matlab?
Suppose:
A= [2 2 3 3 3 4 4 4 5 5 6 6 7 8 8]
so i want to Find that
on index 2,3,4,5,6 values or same or not ?
Note: Index can be Dynamically Entered.
Number(length) of Values in Array also can be changed..
To check if they are all equal: use diff to subtract pairs of values, and then check if all those differences are 0.
A = [2 2 3 3 3 4 4 4 5 5 6 6 7 8 8];
ind = [2 3 4 5 6];
result = ~any(diff(A(ind)));
This is faster than using unique. With A and ind as in your example,
>> tic
for cont = 1:1e5
result = ~any(diff(A(ind)));
end
toc
tic
for cont = 1:1e5
result=numel(unique(A(ind)))==1;
end
toc
Elapsed time is 0.371142 seconds.
Elapsed time is 4.754007 seconds.
Hey this should do the trick:
A= [2 2 3 3 3 4 4 4 5 5 6 6 7 8 8];
B= [1,3,5];
C=A(B);
result=numel(unique(C))==1;
Here A is your data.
B is the index vector.
C contains the elements corresponding to the index vector.
result is 1 if all values were the same and 0 otherwise.
You can even "shorten" the code further by joining the two line:
result=numel(unique(A(B)))==1;
There are some ways, it depends on your taste.
For example, if the variable indexing contain the corresponding indexes:
unique(A(indexing));
will give you a vector with the unique elements in the sub-vector A(indexing). Then you just need to check the length:
length(unique(A(indexing))) == 1
I would avoid the use of numel when the function length is available (it is much more clearer what you are trying to achieve).
Other option is to compare the first element to the rest of the element in the sub-vector:
sub_vector = A(indexing);
all(sub_vector == sub_vector(1));
The second option assumes that the sub-vector will never be empty!

Merge arrays with unequal number of columns

I have around 100 1D arrays I'd like to merge to a matrix.
The arrays have 140 to 180 columns.
Is it possible to merge these 1 x (140-180) arrays to a matrix with a dimension of 100 (amount of arrays) x 180 ?
All the arrays contain numbers. I want to expand the 1x140 array to a 1x180 array by means of interpolation.
In a simplified form, it should be something like this:
A = [1 5 7 8 3]
B = [1 3 5]
result=
[1 5 7 8 3
1 2 3 4 5]
The array B (1x3) is expanded to an 1x5 matrix. And the values in between are interpolated.
Basically, I thought of using "vertcat" after all arrays are expanded by a same amount of columns.
Thanks in advance,
Koen
How about this?
array = {[1 5 7 8 3],[1 3 5]}; % example data
N = 5; % desired length (180 in your case)
aux = cellfun(#(v) interp1(linspace(0,1,length(v)),v,linspace(0,1,N)), array, 'uni', false);
result = cat(1,aux{:});
It uses linear interpolation. For your example, this gives
>> result
result =
1 5 7 8 3
1 2 3 4 5
Note that linear interpolation modifies all values of the vector except first and last, in general. For example, with N=5 the vector [1 3 4 5] would get interpolated to [1 2.5 3.5 4.25 5]. You could use other forms of interpolation by passing an extra argument to interp1, see help interp1.

Resources