How to count number of 1's in the matrix - matlab

I have one matrix like-
A=[1 1 3 0 0;
1 2 2 0 0;
1 1 1 2 0;
1 1 1 1 1];
From these "A" i need to count the number of 1"s of each row and after that i want to give the condition that after scanning each row of 'A' if the number of 1's >=3 then it take that. It means my final result will be
A= [1 1 1 2 0;
1 1 1 1 1].
How can I do this. Matlab experts need your valuable suggestion.

>> A(sum(A == 1, 2) >= 3, :)
ans =
1 1 1 2 0
1 1 1 1 1
Here, sum(A == 1, 2) counts the number of ones in each row, and A(... >= 3, :) selects the rows where the count is at least 3.

A=[1 1 3 0 0;...
1 2 2 0 0;...
1 1 1 2 0;...
1 1 1 1 1]
accept = sum((A == 1)')
i = 1;k = 1;
while i <= length(A(:,1))
if accept(k) < 3
A(i,:) = [];
i = i - 1;
end
i = i + 1;
k = k + 1;
end
A

Related

delete rows in matrix in conditions in matlab

My program creates a matrix whose cell values ​​in multiple rows are the same in the corresponding column. I want to delete some rows that have 0 more than one. To clarify, my matrix has the following form,
A=[ 1 1 1 0 0 1 1 1; 1 0 0 1 1 1 1 1 1; 1 1 1 1 1 1 1 0; 1 1 1 1 0 1 1 1
1 1 0 1 0 0 1 1 ]
and I want to delete all the columns that are in the first, second and fifth rows because the number 0 is 2
or more left in the matrix of rows that are in the third and fourth rows because they have 0 one in each row.
The result should be the following matrix:
A=[ 1 1 1 1 1 1 1 1 0; 1 1 1 1 0 1 1 1 ]
i write this code for your algorithm than work correctly:
% Input Matrix
A = [1 1 1 0 0 1 1 1;1 0 0 1 1 1 1 1; 1 1 1 1 1 1 1 0;1 1 1 1 0 1 1 1;1 1 0 1 0 0 1 1 ];
% find number of rows and cols
[num_rows, num_cols] = size(A);
% Itrate on each row and find rows that have less than 2 zeros
selected_rows = [];
idx = 1;
for i=1:num_rows
num_zero = sum(A(i, 1:end) == 0);
if num_zero < 2
selected_rows(idx) = i;
idx = idx+1;
end
end
% return result matrix
result = [];
for i=1:length(selected_rows)
result = [result; A(selected_rows(i), 1:end)];
end
disp(result)

Finding a critical point in matrix

I'm attempting to find a critical point in a matrix. The value at index (i,j) should be greater than or equal to all elements in its row, and less than or equal to all elements in its column.
Here is what I have (it's off but I'm close):
function C = critical(A)
[nrow ncol] = size(A);
C = [];
for i = 1:nrow
for j = 1:ncol
if (A(i,j) >= A(i,1:end)) && (A(i,j) <= A(1:end,j))
C = [C ; A(i,j)]
end
end
end
You can use logical indexing.
minI = min(A,[],1);
maxI = max(A,[],2);
[row,col] = find(((A.'==maxI.').' & A==minI) ==1)
Details
Remember that Matlab is column major. We therefore transpose A and maxI.
A = [
3 4 1 1 2
2 4 2 1 4
4 3 2 1 2
3 3 1 1 1
2 3 0 2 1];
A.'==maxI.'
ans =
0 0 1 1 0
1 1 0 1 1
0 0 0 0 0
0 0 0 0 0
0 1 0 0 0
Then do the minimum
A==minI
ans =
0 0 0 1 0
1 0 0 1 0
0 1 0 1 0
0 1 0 1 1
1 1 1 0 1
And then multiply the two
((A.'==maxI.').' & A==minI)
ans =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 1 0 0 0
0 1 0 0 0
Then find the rows and cols
[row,col] = find(((A.'==maxI.').' & A==minI) ==1)
row =
4
5
col =
2
2
Try this vectorised solution using bsxfun
function [ r,c,criP ] = critical( A )
%// finding the min and max values of each col & row resptly
minI = min(A,[],1);
maxI = max(A,[],2);
%// matching all the values of min & max for each col and row resptly
%// getting the indexes of the elements satisfying both the conditions
idx = find(bsxfun(#eq,A,maxI) & bsxfun(#eq,A,minI));
%// getting the corresponding values from the indexes
criP = A(idx);
%// Also getting corresponding row and col sub
[r,c] = ind2sub(size(A),idx);
end
Sample Run:
r,c should be a vector of equal length which represents the row and column subs of each Critical point. While val is a vector of same length giving the value of the critical point itself
>> A
A =
3 4 1 1 2
2 4 2 1 4
4 3 2 1 2
3 3 1 1 1
2 3 0 2 1
>> [r,c,val] = critical(A)
r =
4
5
c =
2
2
val =
3
3
I think there is a simpler way with intersect:
>> [~, row, col] = intersect(max(A,[],2), min(A));
row =
4
col =
2
UPDATE:
With intersect, in case you have multiple critical points, it will only give you the first one. To have all the indicies, there is also another simple way:
>> B
B =
3 4 1 4 2 5
2 5 2 4 4 4
4 4 2 4 2 4
3 4 1 4 1 4
2 5 4 4 4 5
>> row = find(ismember(max(B,[],2),min(B)))
row =
3
4
>> col = find(ismember(min(B),max(B,[],2)))
col =
2 4 6
Note that the set of critical points now should be the combination of row and col, means you have total 6 critical points in this example: (3,2),(4,2),(3,4),(4,4),(3,6),(4,6).
Here you can find how to export such combination.

Split Matrix into several depending on value matlab

I am trying to split an nx3 matrix into submatrices in matlab. So my matrix C is of this shape
C =
1 1 1
0 0 0
0 0 0
1 1 1
1 1 1
1 1 1
0 0 0
1 1 1
1 1 1
It either has rows of zeros or rows of ones. I want to split this matrix to only keep matrices of ones. So here for instance there's three 'groups' of ones. so I want to get
C1 =
1 1 1
C2 =
1 1 1
1 1 1
1 1 1
C3 =
1 1 1
1 1 1
However my real matrix is an n by 3, so i don't know where the ones are.
Edit 1:
Now, i need to split x1 and y1 (individual row vectors with same length as C) to x(1), x(2),.. (similarly for y vector) based on how the matrix C was split
Sample Input:
x1 = (1:9)';
y1 = (2:2:18)';
Desired Output:
x(1)=[1], x(2)=[4 5 6]' and x(3)=[8 9]'
y(1)=[2], y(2) =[8 10 12]' and y(3)=[16 18]'
Use find function to the first column to find the indices of 1-elements. Then, calculate the relative distance between any two consecutive elements of the obtained vector to determine the boundary. After that, use matrix indexing to get the blocks of 1-element-matrices. Let me know if you have a better idea.
c=[1 1 1;
0 0 0;
0 0 0;
1 1 1;
1 1 1;
1 1 1;
0 0 0;
1 1 1;
1 1 1;]
b=c(:, 1);
find(b);
I will leave the rest to yourself.
Input:
c = [1 1 1;
0 0 0;
0 0 0;
1 1 1;
1 1 1;
1 1 1;
0 0 0;
1 1 1;
1 1 1;]
x1 = (1:9)';
y1 = (2:2:18)';
Code:
elementalLengthA = cellfun('length',regexp(sprintf('%i',all(C,2)),'1+','match'));
elementalStartA = regexp(sprintf('%i',all(C,2)),'1+','start');
result = cell(length(elementalLengthA),1);
x = cell(length(elementalLengthA),1);
y = cell(length(elementalLengthA),1);
for i = 1:length(elementalLengthA)
result(i) = {C(elementalStartA(i):elementalStartA(i)+elementalLengthA(i)-1,:)};
x(i) = {x1(elementalStartA(i):elementalStartA(i)+elementalLengthA(i)-1,:)};
y(i) = {y1(elementalStartA(i):elementalStartA(i)+elementalLengthA(i)-1,:)};
end
Output:
>> cell2mat(result(1))
ans =
1 1 1
>> cell2mat(result(2))
ans =
1 1 1
1 1 1
1 1 1
>> cell2mat(result(3))
ans =
1 1 1
1 1 1
>> cell2mat(x(3)) %similarly do it for other cells to get results
ans =
8
9

Generate derived matrix from index vector in matlab

Consider an index vector consisting of ones and zeros:
I=[0 0 1 0 1 1 0 0 0];
How can I easily generate the following matrix in matlab:
J=[0 2;
1 1;
0 1;
1 2;
0 3];
Use diff:
I = [0 0 1 0 1 1 0 0 0];
d = diff(I);
ind = [1 find(d~=0)+1]; %// starting index of each new value
rep = diff([ind numel(I)+1]); %// number of repetitions of each new value
J = [ I(ind).' rep.' ];
Using strfind for a slightly bigger example -
I =[1 1 0 0 1 0 1 1 0 0 0 1 1 1 1 0 0]
zero_pos = ['0' num2str(bsxfun(#eq,I,0),'%1d') '0']
ind3 = [ strfind(zero_pos,'01') ; strfind(zero_pos,'10')]
counts = diff(ind3(:))
var = zeros(numel(counts),1);
var(2:2:end)=1;
J = [var counts];
if ind3(1,1)-1>0
J = [1 ind3(1,1)-1;J];
end
Output
J =
1 2
0 2
1 1
0 1
1 2
0 3
1 4
0 2

Using matrix rows as index range on a vector?

I have this matrix:
A = [1 3
5 7
9 10];
And this vector:
B = zeros(1,10);
Now I want to change the elements in the ranges of [1:3],[5:7] and [9:10] to 1 .
So, to get this:
C = [1 1 1 0 1 1 1 0 1 1];
I tried:
B(A(:,1):A(:,2)) = 1;
but it just changes the zeros in the first range.
Can it be done without a for loop?
Thanks.
The first column of A are starting positions and the second one are ending positions of each sequence of 1s. To denote a beginning use 1 and for the end -1, then cumsum().
% Preallocate
N = 10;
B = zeros(1,N);
B(A(:,1)) = 1
B =
1 0 0 0 1 0 0 0 1 0
B(A(:,2)+1) = -1
B =
1 0 0 -1 1 0 0 -1 1 0 -1
B = cumsum(B)
B =
1 1 1 0 1 1 1 0 1 1 0
B(1:N)
ans =
1 1 1 0 1 1 1 0 1 1
Would something like this be appropriate?
>> f = #(x)(any(A(:,1)<=x & x<=A(:,2)));
>> i = 1:length(B)
i =
1 2 3 4 5 6 7 8 9 10
>> arrayfun(f,i)
ans =
1 1 1 0 1 1 1 0 1 1
Hello you can try this:
B([A(1,1):A(1,2) A(2,1):A(2,2) A(3,1):A(3,2)]) = 1;