expand matrix in matlab? - matlab

I would like to expand matrix row by row under a conditional statement without initializing the matrix. In C++, simply I use std::vector and push_back method without initializing the size of the vector in C++. However, I want to do same scenario in Matlab. This is my pseudo code
for i = 1:lengt(data)
if ( condition )
K = [data(1) data(2) i]
end
K

Let us assume some working code to resemble your pseudo-code.
%// Original code
for i = 1:10
if rand(1)>0.5
data1 = rand(2,1)
K = [data1(1) data1(2) i]
end
end
Changes for "pushing data without initialization/pre-allocation":
To save data at each iteration we keeping on "stacking" data along a chosen dimension. This could be thought of as pushing data. For a 2D case, use either a "row vector push" or a "column vector push". For this case we are assuming a former case.
We don't index into K using the original iterator, but use a custom one,
that only increments when the condition is satisfied.
The code below must make it clear.
%// Modified code
count = 1; %// Custom iterator; initialize it for the iteration when condition would be satisfied for the first time
for i = 1:10
if rand(1)>0.5
data1 = rand(2,1)
K(count,:) = [data1(1) data1(2) i] %// Row indexing to save data at each iteration
count = count +1; %// We need to manually increment our custom iterator
end
end

If we assume from the above that data is an Nx2 matrix, and that you only want to save the rows that satisfy some condition, then you almost have the correct code to update your K matrix without having to initialize it to some size:
K = []; % initialize to an empty matrix
for i=1:size(data,1) % iterate over the rows of data
if (condition)
% condition is satisfied so update K
K = [K ; data(i,:) i];
end
end
K % contains all rows of data and the row number (i) that satisfied condition
Note that to get all elements from a row, we use the colon to say get all column elements from row i.

Related

How do i handle "Error using vertcat Dimensions of matrices being concatenated are not consistent" in Matlab?

So I want to concatenate an m x n matrix to obtain a 1 x mn matrix. The matrix I want to concatenate are generated from a while loop. Although the number of columns will always be 3, I however cannot tell how many rows there will be for each iteration. Also, the row sizes for each iteration may not always be the same.
The code runs in cases where the row sizes were all equal to 6, but in cases where they aren't equal I get an error:
Error using vertcat Dimensions of matrices being concatenated are not consistent.
parts of the code are as follows:
A = [];
B = [];
searchArea = 2;
for ii = 1: numel(velocity)
Do ....
while area(ii,:) < searchArea
Do ....
% COLLATE vectors for A
A = [A; [Ax(ii), Ay(ii), Az(ii)]];
Do ...
end
%# Copy the A into new variable (B) and Reshape into row vector so as to associate each row to its corresponding velocity
B = [B; reshape(A.',1,[])];
A = [];
end
Could someone please advice me on what I am doing wrong here. I would clarify further if there be need. Thanks guys!
If it's your intent that B ends up being a row vector, then you need to change this:
B = [B; reshape(A.',1,[])]; % Does vertical concatenation
to this:
B = [B reshape(A.',1,[])]; % Does horizontal concatenation (note there's no semicolon)
so that each row vector gotten from reshaping A gets added to the end of the row instead of as a new row (as the semicolon indicates).

how to check the values of each variables from a resultant matrix in matlab?

I have sum of 3 cell arrays
A=72x1
B=72x720
C=72x90
resultant=A+B+C
size of resultant=72x64800
now when I find the minimum value with row and column indices I can locate the row element easily but how can I locate the column element in variables?
for example
after dong calculations for A,B,C I added them all and got a resultant in from of <72x(720x90)> or can say a matrix of integers of size <72x64800> then I found the minimum value of resultant with row and column index using the code below.
[minimumValue,ind]=min(resultant(:));
[row,col]=find(result== minimumValue);
then row got 14 and column got 6840 value..
now I can trace row 14 of all A,B,C variables easily but how can I know that the resultant column 6480 belongs to which combination of A,B,C?
Instead of using find, use the ind output from the min function. This is the linear index for minimumValue. To do that you can use ind2sub:
[r,c] = ind2sub(size(resultant),ind);
It is not quite clear what do you mean by resultant = A+B+C since you clearly don't sum them if you get a bigger array (72x64800), on the other hand, this is not a simple concatenation ([A B C]) since this would result in a 72x811 array.
However, assuming this is a concatenation you can do the following:
% get the 2nd dimension size of all matrices:
cols = cellfun(#(x) size(x,2),{A,B,C})
% create a vector with reapiting matrices names for all their columns:
mats = repelem(['A' 'B' 'C'],cols);
% get the relevant matrix for the c column:
mats(c)
so mats(c) will be the matrix with the minimum value.
EDIT:
From your comment I understand that your code looks something like this:
% arbitrary data:
A = rand(72,1);
B = rand(72,720);
C = rand(72,90);
% initializing:
K = size(B,2);
N = size(C,2);
counter = 1;
resultant = zeros(72,K*N);
% summing:
for k = 1:K
for n = 1:N
resultant(:,counter) = A + B(:,k) + C(:,n);
counter = counter+1;
end
end
% finding the minimum value:
[minimumValue,ind] = min(resultant(:))
and from the start of the answer you know that you can do this:
[r,c] = ind2sub(size(resultant),ind)
to get the row and column of minimumValue in resultant. So, in the same way you can do:
[Ccol,Bcol] = ind2sub([N,K],c)
where Bcol and Ccol is the column in B and C, respectively, so that:
minimumValue == A(r) + B(r,Bcol) + C(r,Ccol)
To see how it's working imagine that the loop above fills a matrix M with the value of counter, and M has a size of N-by-K. Because we fill M with a linear index, it will be filled in a column-major way, so the row will correspond to the n iterator, and the column will correspond to the k iterator. Now c corresponds to the counter where we got the minimum value, and the row and column of counter in M tells us the columns in B and C, so we can use ind2sub again to get the subscripts of the position of counter. Off course, we don't really need to create M, because the values within it are just the linear indices themselves.

storing values from a matrix to another one with an if operation using matlab

I have a "x1" matrix, and I want to extract some particular elements with respect to a logical condition:
for z=1:length(x1)
if (x1(z+1)-x1(z))>=20)
extract=
end
end
How can I obtain the "extract" matrix and the indices of these values in x1?
The index of the elements in x1 is obviously z itself: the z-th element satisfies that condition. In extract I suppose you want to put x1(z), so that's the value. But extract may have less elements than x1 so we need a proper index to run through extract, let's call it k.
k=1
for z=1:length(x1)-1
if (x1(z+1)-x1(z))>=20)
extract(k)=x1(z); %if you want to extract the value
k=k+1;
end
end
or, if you want to save the index of x1 and not the value
k=1
for z=1:length(x1)-1
if (x1(z+1)-x1(z))>=20)
extract(k)=z;
k=k+1;
end
end
At the end of this loop, extract will be an array containing all the values (first loop) or the indices (second loop) of the elements in x1 that satisfy your condition.
For the sake of completeness, to obtain both, we must engage two arrays (extract for the values and indices for the indices):
k=1
for z=1:length(x1)-1
if (x1(z+1)-x1(z))>=20)
extract(k)=x1(z); % store the value
indices(k)=z; % store the index
k=k+1;
end
end
You can use this code to extract the indices
x1Diff = diff(x1)
x1DiffTh = zeros(size(x1Diff))
x1DiffTh[x1Diff>20] = 1
indx = find(x1DiffTh)
Or compacted in 1 line
indx = find(diff(x1)>20)
For loops are very ineficient in Matlab since the code is not compiled.

MatLab: Sorting two row vectors

I have two row vectors (i_1,i_2,...,i_n) and (b_1,b_2,...,b_n) where i_1 corresponds to b_1.
I need to consider the case where the i elements are not necessarily in order so must be sorted, how do I do this while also making sure the b elements are rearranged so that they still correspond to the correct i element. I have the following sorting code that I need to use but am unsure how to adapt it to do what I need it to.
function [ out ] = myMsort( a )
%MYMSORT returns a sorted version of the input row vector, by merging
% Merge sort: running time O(n log n) with n elements to sort
% But really quite inefficient for small n
n=length(a);
if (n==1)
out=a; return
end
out=myMerge(myMsort(a(1,1:floor(n/2))),myMsort(a(1,floor(n/2)+1:n)));
end
Where the function called within this is as follows
function [ out ] = myMerge( a,b )
% MYMERGE: takes two sorted row vectors and produces the (sorted) merge
% running time linear in output size
out=zeros(1,length(a)+length(b)); % Avoid growing array!
j=1;k=1;l=1;
while (j<=length(a))&&(k<=length(b))
if (a(1,j)<b(1,k))
out(1,l)=a(1,j); j=j+1;l=l+1;
else
out(1,l)=b(1,k); k=k+1;l=l+1;
end
end
while (j<=length(a))
out(1,l)=a(1,j); j=j+1;l=l+1;
end
while (k<=length(b))
out(1,l)=b(1,k); k=k+1;l=l+1;
end
end
Any help would be much appreciated.
You can modify the code to accept multiple rows of data, but still just sort all columns based on the values in the first row. This requires only small changes: first, change every instance of length(a) or length(b) to size(a,2) and size(b,2). Then make sure in the merge assignments you transfer all elements from that column by using the : indexing operator, instead of 1.
function [ out ] = myMsort( a )
n=size(a,2);
if (n==1)
out=a;
return
end
out=myMerge(myMsort(a(:,1:floor(n/2))),myMsort(a(:,floor(n/2)+1:n)));
end
function [ out ] = myMerge( a,b )
out=zeros(size(a,1),size(a,2)+size(b,2)); % Avoid growing array!
j=1;k=1;l=1;
while (j<=size(a,2))&&(k<=size(b,2))
if (a(1,j)<b(1,k))
out(:,l)=a(:,j);
j=j+1;l=l+1;
else
out(:,l)=b(:,k);
k=k+1;l=l+1;
end
end
while (j<=size(a,2))
out(:,l)=a(:,j);
j=j+1;l=l+1;
end
while (k<=size(b,2))
out(:,l)=b(:,k);
k=k+1;l=l+1;
end
end
Now you can run the code like so:
n = 100;
i = rand([1 n]);
b = rand([1 n]);
out = myMsort([i;b]);
And out will be a matrix of two rows: row 1 is the sorted values of i and row 2 is the corresponding values from b.
Just little modification, here my example :
a = [12,4,1,2,8,7];
and into myMsort, I change :
out=myMerge(myMsort(a(1:floor(n/2))),myMsort(a(floor(n/2)+1:n)));
where all line are already sorted.
I don't really understand the part a is two row
EDIT
here the full myMsort function :
function [ out ] = myMsort( a )
%MYMSORT returns a sorted version of the input row vector, by merging
% Merge sort: running time O(n log n) with n elements to sort
% But really quite inefficient for small n
a = reshape(a,1,size(a,1)*size(a,2));
n=length(a);
if (n==1)
out=a; return
end
out=myMerge(myMsort(a(1:floor(n/2))),myMsort(a(floor(n/2)+1:n)));
end
Note that i'm using reshape to make a single row array. You can do it by yourself with another function. the problem is with the recursion your out need to be 2 row vector but it not when myMerge return.

remove cells that satisfy a specific condition

I have a cell array which each cell is an n-by-n matrix. I want to delete the cells for which inv(cell{i}'*cell{i}) gives warning that matrix is close to singular.
Thank you
In general, removing elements is the easy part. If C is your array, removing cells specified by the indices in vector idx can be done by:
C(idx) = {};
Regarding your specific problem, to check if a matrix is "almost" singular or not can be done with rcond (if the result is close to zero, it's probably singular). To apply it to all cells you can use cellfun in the following way:
idx = cellfun(#(x)(rcond(x' * x) < 1e-12), C);
Adjust the threshold value to your liking. The resulting idx is a logical array with 1s at the location of singular matrices. Use idx to remove these elements from C as shown above.
Create a function that check for your condition:
function state = CheckElement(element)
if ([condition])
state = 1;
else
state = 0;
end
end
then do cellfun on all you cell array elements like the following:
indices = cellfun(#CheckElement,myCellArray);
cellArray(indices ) = [];
Assuming you have already defined a issingular function defined you can use cellfun to get the indices of the cells that contain the matrices you want to remove.
c; % cell arry
singularIdx = cellfun((#x) issingular( inv(x' * x)), c); %' added single quote for SO syntax
cFiltered = c(~singluarIdx);
You'll probably need to write your own function to check for singularity, for more information on that see this question: Fast method to check if a Matrix is singular? (non-invertible, det = 0)