How can you remove matrix rows in Matlab based on some criteria? - matlab

In Matlab, how can I remove spesific rows from a matrix I require? If for example I would like to remove all rows from a matrix which contain a spesific value (like 0 or NaN)?

Let's say you have A
A = [1 2 3;4 5 0; 7 8 9; 10 NaN 12]
A =
1 2 3
4 5 0
7 8 9
10 NaN 12
Then, you can choose the rows as follows:
any(isnan(A'))
ans =
0 0 0 1
To delete those NaN-containing rows, you can do:
A(any(isnan(A')),:) = []
A =
1 2 3
4 5 0
7 8 9
You can choose 0-containing rows by any(A' == 0). If you want all elements to be 0s or NaNs, then you can use all instead of any.

Related

How to take union of matrix rows that are represented by another vector?

I want to take the union of some of the rows of a matrix x. The row numbers of the rows whose union has to be taken are given by vector r. Is there any built-in function in MATLAB that can do it?
x = [1 2 4 0 0;
3 6 5 0 0;
7 8 10 12 9;
2 4 6 7 0;
3 4 5 8 12];
r = [1, 3, 5];
I think this will work for you - first, take the submatrix x(r,:) with the rows you want, and then find all the unique values in it:
unique(x(r,:))
ans =
0
1
2
3
4
5
7
8
9
10
12
You could do it like this
>>> union(union(x(r(1),:),x(r(2),:)),x(r(3),:))
ans =
0 1 2 3 4 5 7 8 9 10 12
or set up a for loop that iterates over the vector r to compute all the unions

Removing columns from a Matrix MatLab

[1 2 3 4 5 6 7 8 9 ;
9 8 7 6 5 4 3 2 1 ;
1 2 0 0 1 0 0 0 1 ]
The last row has five columns with zeros. I would like to keep only one column per zero crossing.
like this
[1 2 3 5 8 9 ;
9 8 7 5 2 1 ;
1 2 0 1 0 1 ]
Is this possible with fast Matlab functions or do I have to write some slow complicated for loop ?
You can create a logical array many different ways to find the columns to remove. Something like this would work
% Find the zeros that are not the first zero
cols_to_remove = data(end,:) == 0 & ~diff([false, data(end,:) == 0]) == 1;
% Now remove them
data(:, cols_to_remove) = [];

Dividing a vector to form different matrices

I have a two long vector. Vector one contains values of 0,1,2,3,4's, 0 represent no action, 1 represent action 1 and 2 represent the second action and so on. Each action is 720 sample point which means that you could find 720 consecutive twos then 720 consecutive 4s for example. Vector two contains raw data corresponding to each action. I need to create a matrix for each action ( 1, 2, 3 and 4) which contains the corresponding data of the second vector. For example matrix 1 should has all the data (vector 2 data) which occurred at the same indices of action 1. Any Help??
Example on small amount of data:
Vector 1: 0 0 1 1 1 0 0 2 2 2 0 0 1 1 1 0 0 2 2 2
Vector 2: 6 7 5 6 4 6 5 9 8 7 9 7 0 5 6 4 1 5 8 0
Result:
Matrix 1:
5 6 4
0 5 6
Matrix 2:
9 8 7
5 8 0
Here is one approach. I used a cell array to store the output matrices, hard-coding names for such variables isn't a good plan.
V1=[0 0 1 1 1 0 0 2 2 2 0 0 1 1 1 0 0 2 2 2]
V2=[6 7 5 6 4 6 5 9 8 7 9 7 0 5 6 4 1 5 8 0]
%// Find length of sequences of 1's/2's
len=find(diff(V1(find(diff(V1)~=0,1)+1:end))~=0,1)
I=unique(V1(V1>0)); %// This just finds how many matrices to make, 1 and 2 in this case
C=bsxfun(#eq,V1,I.'); %// The i-th row of C contains 1's where there are i's in V1
%// Now pick out the elements of V2 based on C, and store them in cell arrays
Matrix=arrayfun(#(m) reshape(V2(C(m,:)),len,[]).',I,'uni',0);
%// Note, the reshape converts from a vector to a matrix
%// Display results
Matrix{1}
Matrix{2}
Since, there is a regular pattern in the lengths of groups within Vector 1, that could be exploited to vectorize many things while proposing a solution. Here's one such implementation -
%// Form new vectors out of input vectors for non-zero elements in vec1
vec1n = vec1(vec1~=0)
vec2n = vec2(vec1~=0)
%// Find positions of group shifts and length of groups
df1 = diff(vec1n)~=0
grp_change = [true df1]
grplen = find(df1,1)
%// Reshape vec2n, so that we end up with N x grplen sized array
vec2nr = reshape(vec2n,grplen,[]).' %//'
%// ID/tag each group change based on their unique vector 2 values
[R,C] = sort(vec1n(grp_change))
%// Re-arrange rows of reshaped vector2, s.t. same ID rows are grouped succesively
vec2nrs = vec2nr(C,:)
%// Find extents of each group & use those extents to have final cell array output
grp_extent = diff(find([1 diff(R) 1]))
out = mat2cell(vec2nrs,grp_extent,grplen)
Sample run for the given inputs -
>> vec1
vec1 =
0 0 1 1 1 0 0 2 2 2 ...
0 0 1 1 1 0 0 2 2 2
>> vec2
vec2 =
6 7 5 6 4 6 5 9 8 7 ...
9 7 0 5 6 4 1 5 8 0
>> celldisp(out)
out{1} =
5 6 4
0 5 6
out{2} =
9 8 7
5 8 0
Here is another solution:
v1 = [0 0 1 1 1 0 0 2 2 2 0 0 1 1 1 0 0 2 2 2];
v2 = [6 7 5 6 4 6 5 9 8 7 9 7 0 5 6 4 1 5 8 0];
m1 = reshape(v2(v1 == 1), 3, [])'
m2 = reshape(v2(v1 == 2), 3, [])'
EDIT: David's solution is more flexible and probably more efficient.

matlab adjacency list to adjacency matrix

How to convert adjacency list to adjacency matrix via matab
For example: Here is the adjacency list(undirected), the third column is the weight.
1 2 3
1 3 4
1 4 5
2 3 4
2 5 8
2 4 7
++++++++++++++++++++++
that should be converted to:
1 2 3 4 5
1 0 4 5 0
2 3 4 7 8
3 4 7 0 0
4 0 7 0 0
5 0 8 0 0
You can use sparse matrix. Let rows be the first column, cols the second, and s the weight.
A = sparse([rows; cols],[cols; rows],[s; s]);
If you want to see the matrix. use full().
UPDATE:
I made the answer a bit simpler (everything in one line, instead of adding the transposed, and included explanations, as requested:
list = [1 2 3
1 3 4
1 4 5
2 3 4
2 5 8
2 4 7];
rows = list(:,1)
cols = list(:,2)
s = list(:,3)
Now, rows, cols and s contains the needed information. Sparse matrices need three vectors. Each row of the two first vectors, rows and cols is the index of the value given in the same row of s (which is the weight).
The sparse command assigns the value s(k) to the matrix element adj_mat(rows(k),cols(k)).
Since an adjacency matrix is symmetric, A(row,col) = A(col,row). Instead of doing [rows; cols], it is possible to first create the upper triangular matrix, and then add the transposed matrix to complete the symmetric matrix.
A = sparse([rows; cols],[cols; rows],[s; s]);
full(A)
A =
0 3 4 5 0
3 0 4 7 8
4 4 0 0 0
5 7 0 0 0
0 8 0 0 0
It's really hard to tell what your'e asking. Is this right?
list = [1 2 3
1 3 4
1 4 5
2 3 4
2 5 8
2 4 7];
matrix = zeros(max(max(list(:, 1:2)))); %// Or just zeros(5) if you know you want a 5x5 result
matrix(sub2ind(size(matrix), list(:,1), list(:,2))) = list(:,3); %// Populate the upper half
matrix = matrix + matrix' %'// Find the lower half via symmetry
matrix =
0 3 4 5 0
3 0 4 7 8
4 4 0 0 0
5 7 0 0 0
0 8 0 0 0

How to split 1xN vector into MxL vector and fill the rest with zeros?

I have a matrix
a = [1 2 3 4 5 6 7 8 9 10 11]
I need to split it into rows of 5 and fill the rest of the unset block with zeros like this:
transformed = [ 1 2 3 4 5 ;
6 7 8 9 10;
11 0 0 0 0 ]
You could first expand a to have the required number of elements like this;
a(15) = 0 % Matlab will automatically fill elements 12:14 with 0
then
transformed = reshape(a,[5,3])'
produces
ans =
1 2 3 4 5
6 7 8 9 10
11 0 0 0 0