How to delete rows without using break in matlab - matlab

So this is my code:
in=-8:8;
%calculate z
[h,k,l]=meshgrid(in);
z = (h.^2 + k.^2 + l.^2);
%sort absolute values ascending, which allows to use unique
ac=sort(abs([h(:) k(:) l(:)]),2);
%use unique to identify duplicates
[f,g,p]=unique(ac,'rows');
%count
cnt=histc(p,1:max(p));
% create a matrix with all vectors
disp([h(g),k(g), l(g),z(g),cnt])
i just want to delete or terminate rows containing z>59, i can't used break because it only works in for loop or while loop, so what other command may i used? thanks.

I'd guess you want this:
%// your output matrix you want to filter
output = [h(g),k(g), l(g),z(g),cnt];
%// delete rows containing z > 59 (z is the 4th column)
filtered_output = output(output(:,4) <= 59,:)

Related

Create a submatrix using random columns and loop

I have a 102-by-102 matrix. I want to select square sub-matrices of orders from 2 up to 8 using random column numbers. Here is what I have done so far.
matt is the the original matrix of size 102-by-102.
ittr = 30
cols = 3;
for i = 1:ittr
rr = randi([2,102], cols,1);
mattsub = matt([rr(1) rr(2) rr(3)], [rr(1) rr(2) rr(3)]);
end
I have to extract matrices of different orders from 2 to 8. Using the above code I would have to change the mattsub line every time I change cols. I believe it is possible to do with another loop inside but cannot figure out how. How can I do this?
There is no need to extract elements of a vector and concatenate them, just use the vector to index a matrix.
Instead of :
mattsub = matt([rr(1) rr(2) rr(3)], [rr(1) rr(2) rr(3)]);
Use this:
mattsub = matt(rr, rr);
Defining a set of random sizes is pretty easy using the randi function. Once this is done, they can be projected along your iterations number N using arrayfun. Within the iterations, the randperm and sort functions can be used in order to build the random indexers to the original matrix M.
Here is the full code:
% Define the starting parameters...
M = rand(102);
N = 30;
% Retrieve the matrix rows and columns...
M_rows = size(M,1);
M_cols = size(M,2);
% Create a vector of random sizes between 2 and 8...
sizes = randi(7,N,1) + 1;
% Generate the random submatrices and insert them into a vector of cells...
subs = arrayfun(#(x)M(sort(randperm(M_rows,x)),sort(randperm(M_cols,x))),sizes,'UniformOutput',false);
This can work on any type of matrix, even non-squared ones.
You don't need another loop, one is enough. If you use randi to get a random integer as size of your submatrix, and then use those to get random column and row indices you can easily get a random submatrix. Do note that the ouput is a cell, as the submatrices won't all be of the same size.
N=102; % Or substitute with some size function
matt = rand(N); % Initial matrix, use your own
itr = 30; % Number of iterations
mattsub = cell(itr,1); % Cell for non-uniform output
for ii = 1:itr
X = randi(7)+1; % Get random integer between 2 and 7
colr = randi(N-X); % Random column
rowr = randi(N-X); % random row
mattsub{ii} = matt(rowr:(rowr+X-1),colr:(colr+X-1));
end

How to remove the unconnected nodes from an adjacency matrix?

I have an adjacency matrix(n*n) of 1's and 0's extracted from an unweighted and undirected graph, my goal is to remove all-zeros columns from this matrix and their corresponding rows which are not connected to any node from the graph.
I want to apply one algorithm by using this adjacency matrix but sadly NaN produces because of some columns in this matrix are all 0's. So, i only need the connected components.
fid= fopen('file.txt','rt');
format = repmat('%q',[1 2]);
filee= textscan(fid,format,'Delimiter', '\t');
fclose(fid);
AA2= [filee{:, 1} , filee{:, 2}];
[nodenames, ~, id] = unique(AA2(:));
Adjacency_Matrix= accumarray(reshape(id, size(AA2)), 1, [numel(nodenames), numel(nodenames)]);
Adjoint2 = sum(Adjacency_Matrix~=0,1);
https://drive.google.com/file/d/0B6u8fZadKIp2OFd2X1NrZEdIclU/view
By this command Adjoint2 = sum(Adjacency_Matrix3~=0,1); I can know how many 1's i have in every column. In this matrix, some columns had no 1's, and so don't want them.
As the matrix is (NN) i want to get a (mm) matrix with columns that has only the 1's.
You can use any function:
If the matrix is symmetric you can do this to remove both zero columns and rows:
idx = any(Adjacency_Matrix);
result = Adjacency_Matrix(idx,idx);
else you can generate indexes of both columns and rows:
idx_column = any(Adjacency_Matrix);
idx_row = any(Adjacency_Matrix,2);
Here you can remove both columns and rows
result = Adjacency_Matrix(idx_row, idx_column)
If you want to remove only columns use this:
result = Adjacency_Matrix(:, idx_column)
If you want to remove only rows use this:
result = Adjacency_Matrix(idx_row, :)
This is going to be a brute force solution, since you are using an adjacency matrix. You will have to loop through all of the rows of the matrix and determine which ones are empty, and create a new adjacency matrix from these rows, omitting the correct columns.
You can use the following code:
i = 1;
while(i<=length(A))
if(sum(A(i,:)) == 0 && sum(A(:,i)) == 0)
% node i is isolated
A(:,i) = []; % remove its related column
A(i,:) = []; % remove its related row
else
i = i + 1;
end
end
If sum of elements of a row and respected column is zero, it means this node is isolated. Therefore, you can remove its related row and column.

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.

delete certain columns of matrix when number of zero elements exceeds threshold avoiding loop

I have a quite big (107 x n) matrix X. Within these n columns, each three columns belong to each other. So, the first three columns of matrix X build a block, then columns 4,5,6 and so on.
Within each block, the first 100 row elements of the first column are important X(1:100,1:3:end). Whenever in this first column the number of zeros or NaNs is greater or equal 20, it should delete the whole block.
Is there a way to do this without a loop?
Thanks for any advice!
Assuming the number of columns of the input to be a multiple of 3, there could be two approaches here.
Approach #1
%// parameters
rl = 100; %// row limit
cl = 20; %// count limit
X1 = X(1:rl,1:3:end) %// Important elements from input
match_mat = isnan(X1) | X1==0 %// binary array of matches
match_blk_id = find(sum(match_mat)>=cl) %// blocks that satisfy requirements
match_colstart = (match_blk_id-1).*3+1 %// start column indices that satisfy
all_col_ind = bsxfun(#plus,match_colstart,[0:2]') %//'columns indices to be removed
X(:,all_col_ind)=[] %// final output after removing to be removed columns
Or if you prefer "compact" codes -
X1 = X(1:rl,1:3:end);
X(:,bsxfun(#plus,(find(sum(isnan(X1) | X1==0)>=cl)-1).*3+1,[0:2]'))=[];
Approach #2
X1 = X(1:rl,1:3:end)
match_mat = isnan(X1) | X1==0 %// binary array of matches
X(:,repmat(sum(match_mat)>=cl,[3 1]))=[] %// Find matching blocks, replicate to
%// next two columns and remove them from X
Note: If X is not a multiple of 3, use this before using the codes - X = [X zeros(size(X,1) ,3 - mod(size(X,2),3))].

Deleting matrix elements efficiently

I want to efficiently delete a lot of data from the beginning of a matrix of dimension 2*n. The matrix looks like this:
x1 x2
x3 x4
...
...
I want to delete all rows that have the the first element of a row that is smaller than some number and stop when a row isn't smaller (the elements are in numerical order)
What I do at the moment is slow:
while 1
if list{i}(1) <= someNumber
list{i}(1,:) = []
else
break;
end
end
There must be a neat way of doing this quickly in MATLAB?
Thank you.
One way is to just compare the entire first column in one go and then delete, i.e.
rows2delete = list{i}(:,1) <= someNumber; %# creates logical array with 1 for deletion
list{i}(rows2delete,:) = []; %# delete some rows, all corresponding cols