separation of rows with zero on its 1st column in matlab - matlab

how can separate my matrix like this
A=[0 1 1 4; 1 2 0 8; 0 3 0 5; 2 3 0 4; 2 4 0 3; 3 4 0 2]
my reference is the 1st column. that if the number in the first column is zero i will segregate it like this:
B=[0 1 1 4; 0 3 0 5]
and C=[1 2 0 8; 2 3 0 4; 2 4 0 3; 3 4 0 2]

You can codegolf this but essentially the machinery would be around this type of indexing with a conditional.
>> A=[0 1 1 4; 1 2 0 8; 0 3 0 5; 2 3 0 4; 2 4 0 3; 3 4 0 2];
>> bool = A(:,1)==0;
>> ind = 1:size(A,1);
>> B = A(ind(bool),:);
>> C = A(ind(~bool),:);
>> B
B =
0 1 1 4
0 3 0 5
>> C
C =
1 2 0 8
2 3 0 4
2 4 0 3
3 4 0 2
>>

Related

Block matrix creation

I have two matrices A and D with sizes mxm. I want to create with these two a block matrix B size mn x mn . For example if n=5 then the output will be
B= D A A A A
A D 0 0 0
A 0 D 0 0
A 0 0 D 0
A 0 0 0 D
I have managed to create this form with many for loops but I would like a quicker solution with functions provided by matlab.
This should do the trick:
m = 3;
n = 5;
mn = m*n;
A_val = 4;
D_val = 2;
% Just an example, you could use rand(m) instead...
A = repmat(A_val,m);
D = repmat(D_val,m);
D_cell = repmat({D},1,n);
B = blkdiag(D_cell{:});
idx_1 = 1:m;
idx_2 = (m+1):mn;
B(idx_2,idx_1) = repmat(A,n-1,1);
B(idx_1,idx_2) = repmat(A,1,n-1);
Output:
B =
2 2 2 4 4 4 4 4 4 4 4 4 4 4 4
2 2 2 4 4 4 4 4 4 4 4 4 4 4 4
2 2 2 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 2 2 2 0 0 0 0 0 0 0 0 0
4 4 4 2 2 2 0 0 0 0 0 0 0 0 0
4 4 4 2 2 2 0 0 0 0 0 0 0 0 0
4 4 4 0 0 0 2 2 2 0 0 0 0 0 0
4 4 4 0 0 0 2 2 2 0 0 0 0 0 0
4 4 4 0 0 0 2 2 2 0 0 0 0 0 0
4 4 4 0 0 0 0 0 0 2 2 2 0 0 0
4 4 4 0 0 0 0 0 0 2 2 2 0 0 0
4 4 4 0 0 0 0 0 0 2 2 2 0 0 0
4 4 4 0 0 0 0 0 0 0 0 0 2 2 2
4 4 4 0 0 0 0 0 0 0 0 0 2 2 2
4 4 4 0 0 0 0 0 0 0 0 0 2 2 2
Average tic-toc performance over 1000 iterations 0.00018 seconds.
For more details about the employed functions, refer to the following links:
blkdiag
repmat
It is easy to do with kronecker product kron:
m = 3; % size of the blocks
n = 5; % number of blocks
A = rand(m); % insert you matrices here
D = rand(m);
maskA = zeros(n); % maskA is the block structure of A
maskA(1,:) = 1;
maskA(:,1) = 1;
maskA(1,1) = 0;
maskD = eye(n); %maskD is the block structure of D
B = kron(maskA,A) + kron(maskD,D);
Here is a way using cell2mat:
C = {zeros(size(A)), D , A};
mat = ones(n);
mat(1:n+1:end)=2;
mat(1,2:end)= 3;
mat(2:end,1)= 3;
out = cell2mat(C(mat));
Here's a way:
A = [10 20; 30 40]; % square matrix
D = [50 60; 70 80]; % square matrix
n = 5; % positive integer
tmp_A = repmat({A}, 1, n-1);
tmp_D = repmat({D}, 1, n-1);
result = [D, horzcat(tmp_A{:}); vertcat(tmp_A{:}), blkdiag(tmp_D{:})]

in matlab,how can i put all zeros in the end of the rows in a matrix? [duplicate]

I have a matrix in MATLAB with zeroes and I would like to get another matrix with the first N non-zero elements in each row. Let's say for example N = 3, and the matrix is
A = [ 0 0 2 0 6 7 9;
3 2 4 7 0 0 6;
0 1 0 3 4 8 6;
1 2 0 0 0 1 3]
I'd like the result to be:
B = [2 6 7;
3 2 4;
1 3 4;
1 2 1]
I have a huge matrix so I would like to do it without a loop, could you please help me? Thanks a lot!
Since MATLAB stores a matrix according to column-major order, I first transpose A, bubble up the non-zeros, and pick the first N lines, and transpose back:
N = 3;
A = [ 0 0 2 0 6 7 9;
3 2 4 7 0 0 6;
0 1 0 3 4 8 6;
1 2 0 0 0 1 3];
Transpose and preallocate output B
At = A';
B = zeros(size(At));
At =
0 3 0 1
0 2 1 2
2 4 0 0
0 7 3 0
6 0 4 0
7 0 8 1
9 6 6 3
Index zeros
idx = At == 0;
idx =
1 0 1 0
1 0 0 0
0 0 1 1
1 0 0 1
0 1 0 1
0 1 0 0
0 0 0 0
Bubble up the non-zeros
B(~sort(idx)) = At(~idx);
B =
2 3 1 1
6 2 3 2
7 4 4 1
9 7 8 3
0 6 6 0
0 0 0 0
0 0 0 0
Select first N rows and transpose back
B(1:N,:)'
You can do the bubbling in row-major order, but you would need to retrieve the row and column subscripts with find, and do some sorting and picking there. It becomes more tedious and less readable.
Using accumarray with no loops:
N = 3;
[ii,jj] = find(A); [ii,inds]=sort(ii); jj = jj(inds);
lininds = ii+size(A,1)*(jj-1);
C = accumarray(ii,lininds,[],#(x) {A(x(1:N)')}); %' cell array output
B = vertcat(C{:})
B =
2 6 7
3 2 4
1 3 4
1 2 1
Usually I don't go with a for loop solution, but this is fairly intuitive:
N = 3;
[ii,jj] = find(A);
B = zeros(size(A,1),N);
for iRow = 1:size(A,1),
nzcols = jj(ii==iRow);
B(iRow,:) = A(iRow,nzcols(1:N));
end
Since you are guaranteed to have more than N nonzeros per row of A, that should get the job done.
One-liner solution:
B = cell2mat(cellfun(#(c) c(1:N), arrayfun(#(k) nonzeros(A(k,:)), 1:size(A,1), 'uni', false), 'uni', false)).'
Not terribly elegant or efficient, but so much fun!
N = 3;
for ii=1:size(A,1);
B(ii,:) = A( ii,find(A(ii,:),N) );
end
Actually , you can do it like the code blow:
N=3
for n=1:size(A,1)
[a b]=find(A(n,:)>0,N);
B(n,:)=A(n,transpose(b));
end
Then I think this B matrix will be what you want.

How to create block matrix from a matrix (the block) and a number (number of repetitions) in Matlab? [duplicate]

This question already has answers here:
MATLAB: Create a block diagonal matrix with same repeating block
(5 answers)
Closed 8 years ago.
Matlab syntax question :
Given some n x d matrix A(say [1 2 3; 4 5 6]), and a number k (say 2), how to create a block matrix in which A appears k times ( [ 1 2 3 0 0 0; 4 5 6 0 0 0 ; 0 0 0 1 2 3; 0 0 0 4 5 6] in my example) ?
Another example, if A is [1 2 3; 4 5 6] and k=3 then the output should be:
[ 1 2 3 0 0 0 0 0 0;
4 5 6 0 0 0 0 0 0;
0 0 0 1 2 3 0 0 0;
0 0 0 4 5 6 0 0 0;
0 0 0 0 0 0 1 2 3;
0 0 0 0 0 0 4 5 6
]
It is quit easy, just make a loop and play with the size of the matrix O:
A =[
1 2 3;
4 5 6]
O = zeros(size(A))
B = [A O; O A]
B =[
1 2 3 0 0 0;
4 5 6 0 0 0;
0 0 0 1 2 3;
0 0 0 4 5 6]
I hope ur looking for this.
clc
A =[
1 2 3;
4 5 6]
O = zeros(size(A))
B = [];
K = 3;
line = [];
for (i=1:K)
line = [];
for (j=1:K)
if (j==i)
line = [line A]
else
line =[line O]
end
end
B = [B; line];
end

Find the first N non-zero elements in each row of a matrix

I have a matrix in MATLAB with zeroes and I would like to get another matrix with the first N non-zero elements in each row. Let's say for example N = 3, and the matrix is
A = [ 0 0 2 0 6 7 9;
3 2 4 7 0 0 6;
0 1 0 3 4 8 6;
1 2 0 0 0 1 3]
I'd like the result to be:
B = [2 6 7;
3 2 4;
1 3 4;
1 2 1]
I have a huge matrix so I would like to do it without a loop, could you please help me? Thanks a lot!
Since MATLAB stores a matrix according to column-major order, I first transpose A, bubble up the non-zeros, and pick the first N lines, and transpose back:
N = 3;
A = [ 0 0 2 0 6 7 9;
3 2 4 7 0 0 6;
0 1 0 3 4 8 6;
1 2 0 0 0 1 3];
Transpose and preallocate output B
At = A';
B = zeros(size(At));
At =
0 3 0 1
0 2 1 2
2 4 0 0
0 7 3 0
6 0 4 0
7 0 8 1
9 6 6 3
Index zeros
idx = At == 0;
idx =
1 0 1 0
1 0 0 0
0 0 1 1
1 0 0 1
0 1 0 1
0 1 0 0
0 0 0 0
Bubble up the non-zeros
B(~sort(idx)) = At(~idx);
B =
2 3 1 1
6 2 3 2
7 4 4 1
9 7 8 3
0 6 6 0
0 0 0 0
0 0 0 0
Select first N rows and transpose back
B(1:N,:)'
You can do the bubbling in row-major order, but you would need to retrieve the row and column subscripts with find, and do some sorting and picking there. It becomes more tedious and less readable.
Using accumarray with no loops:
N = 3;
[ii,jj] = find(A); [ii,inds]=sort(ii); jj = jj(inds);
lininds = ii+size(A,1)*(jj-1);
C = accumarray(ii,lininds,[],#(x) {A(x(1:N)')}); %' cell array output
B = vertcat(C{:})
B =
2 6 7
3 2 4
1 3 4
1 2 1
Usually I don't go with a for loop solution, but this is fairly intuitive:
N = 3;
[ii,jj] = find(A);
B = zeros(size(A,1),N);
for iRow = 1:size(A,1),
nzcols = jj(ii==iRow);
B(iRow,:) = A(iRow,nzcols(1:N));
end
Since you are guaranteed to have more than N nonzeros per row of A, that should get the job done.
One-liner solution:
B = cell2mat(cellfun(#(c) c(1:N), arrayfun(#(k) nonzeros(A(k,:)), 1:size(A,1), 'uni', false), 'uni', false)).'
Not terribly elegant or efficient, but so much fun!
N = 3;
for ii=1:size(A,1);
B(ii,:) = A( ii,find(A(ii,:),N) );
end
Actually , you can do it like the code blow:
N=3
for n=1:size(A,1)
[a b]=find(A(n,:)>0,N);
B(n,:)=A(n,transpose(b));
end
Then I think this B matrix will be what you want.

count match value two matrix using bsxfun

I use c=bsxfun(#eq,b,a) to compare value of two matrix. but I find it difficult to count un-match values. for example, I use this code
a = [1 2 3 4 7 6; ...
3 2 4 6 7 2 ];
b = [1 3 2 4 5 7; ...
3 4 5 6 7 2; ...
2 3 4 5 6 6];
for i = 1:size(a,1)
c= bsxfun(#eq,a(i,:),b)
match = sum(c')
end
and result
c =
1 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
match =
2 1 1
c =
0 0 0 0 0 0
1 0 0 1 1 1
0 0 1 0 0 0
match =
0 4 1
I want to save value first match matrix with second match. for example
total_match =
2 5 2
Do you have any suggestion ? thanks..
No need for loop
match = bsxfun( #eq, permute( a, [1 3 2]), permute( b, [3 1 2] ) ); % result in 2x3x6 boolean
match = sum( match, 3 ); % sum matches across rows of a--b
total_match = sum( match, 1 );
PS
It is best not to use i and j as variable names in Matlab.