How to identify the same number in a matrix? [closed] - matlab

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have a binary matrix, it looks like this:
A = [ 0 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 0;
1 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1; ]
But when I try to put A into a calculation, I only can use vector B, which
is the row sum of matrix A into calculation. B looks like this:
B=[ 1 1 0 1 1 1 0 1 1 0 1 1 0 0 1 1 1];
But I still want to carry the information about which "1" comes from which row of matrix A. I want to know is there any way to add additional conditions to vector B, so that vector B still can carry the information from matrix A, that is which "1" comes from which "row" of matrix A.

Assuming that A only contains 0 and 1 values,
[v, B] = max(A,[],1);
B(v==0) = 0;
gives
B =
2 2 0 1 1 1 0 2 2 0 1 1 0 0 2 3 3
If there are more than one 1 value in a column, this gives the row index of the first one.

Its #luis's idea.. i'm just adding little changes. Also i still don't know whether this is what OP wants.
Created a 3D matrix from luis's solution, So that both the binary values and row info are stored in B. If you want binary values, access slice 1. if you want row info, access slice 2
[B(:,:,1), B(:,:,2)] = max(A);
B(1,~all(B,3),:) = 0;
>> B
B(:,:,1) =
1 1 0 1 1 1 0 1 1 0 1 1 0 0 1 1 1
B(:,:,2) =
2 2 0 1 1 1 0 2 2 0 1 1 0 0 2 3 3
If you want a specific binary value and its row index, say for eg, 8th binary value and its corresponding row index,
>> B(:,8,:)
ans(:,:,1) =
1
ans(:,:,2) =
2

Related

How to create an array according to row and column number [duplicate]

This question already has answers here:
How can I change the values of multiple points in a matrix?
(3 answers)
Closed 6 years ago.
I want to create an array according to row number and column number.
For example :
row_number Column_number Value
1 1 5
3 2 10
4 6 4
7 5 66
The array should look like :
A=
5 0 0 0 0 0
0 0 0 0 0 0
0 10 0 0 0 0
0 0 0 0 0 4
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 66 0
Otherwise it will print zero.
3 possible methods to this regularly asked question:
1. Using the sub2ind function
A = zeros(max(row_number), max(Column_number));
idx = sub2ind(size(A),row_number, Column_number);
A(idx) = Value;
2. Calculating the linear indices manually
A = zeros(max(row_number), max(Column_number));
idx = row_number(:,1) + (Column_number(:,2)-1)*size(A,1)
A(idx) = Value;
3. Use a sparse matrix
sparse(row_number, Column_number, Value)
And then call full on that if you want to convert it to a regular matrix

Assign values w/ multiple conditions

Let's have a M = [10 x 4 x 12] matrix. As example I take the M(:,:,4):
val(:,:,4) =
0 0 1 0
0 1 1 1
0 0 0 1
1 1 1 1
1 1 0 1
0 1 1 1
1 1 1 1
1 1 1 1
0 0 1 1
0 0 1 1
How can I obtain this:
val(:,:,4) =
0 0 3 0
0 2 2 2
0 0 0 4
1 1 1 1
1 1 0 1
0 2 2 2
1 1 1 1
1 1 1 1
0 0 3 3
0 0 3 3
If I have 1 in the first column then all the subsequent 1's should be 1.
If I have 0 in the first column but 1 in the second, all the subsequent 1's should be 2.
If I have 0 in the first and second column but 1 in the third then all the subsequent 1's should be 3.
If I have 0 in the first 3 columns but 1 in the forth then this one should be four.
Note: The logical matrix M is constructed:
Tab = [reshape(Avg_1step.',10,1,[]) reshape(Avg_2step.',10,1,[]) ...
reshape(Avg_4step.',10,1,[]) reshape(Avg_6step.',10,1,[])];
M = Tab>=repmat([20 40 60 80],10,1,size(Tab,3));
This is a very simple approach that works for both 2D and 3D matrices.
%// Find the column index of the first element in each "slice".
[~, idx] = max(val,[],2);
%// Multiply the column index with each row of the initial matrix
bsxfun(#times, val, idx);
This could be one approach -
%// Concatenate input array along dim3 to create a 2D array for easy work ahead
M2d = reshape(permute(M,[1 3 2]),size(M,1)*size(M,3),[]);
%// Find matches for each case, index into each matching row and
%// elementwise multiply all elements with the corresponding multiplying
%// factor of 2 or 3 or 4 and thus obtain the desired output but as 2D array
%// NOTE: Case 1 would not change any value, so it was skipped.
case2m = all(bsxfun(#eq,M2d(:,1:2),[0 1]),2);
M2d(case2m,:) = bsxfun(#times,M2d(case2m,:),2);
case3m = all(bsxfun(#eq,M2d(:,1:3),[0 0 1]),2);
M2d(case3m,:) = bsxfun(#times,M2d(case3m,:),3);
case4m = all(bsxfun(#eq,M2d(:,1:4),[0 0 0 1]),2);
M2d(case4m,:) = bsxfun(#times,M2d(case4m,:),4);
%// Cut the 2D array thus obtained at every size(a,1) to give us back a 3D
%// array version of the expected values
Mout = permute(reshape(M2d,size(M,1),size(M,3),[]),[1 3 2])
Code run with a random 6 x 4 x 2 sized input array -
M(:,:,1) =
1 1 0 1
1 0 1 1
1 0 0 1
0 0 1 1
1 0 0 0
1 0 1 1
M(:,:,2) =
0 1 0 1
1 1 0 0
1 1 0 0
0 0 1 1
0 0 0 1
0 0 1 0
Mout(:,:,1) =
1 1 0 1
1 0 1 1
1 0 0 1
0 0 3 3
1 0 0 0
1 0 1 1
Mout(:,:,2) =
0 2 0 2
1 1 0 0
1 1 0 0
0 0 3 3
0 0 0 4
0 0 3 0

MATLAB Add 1's to matrix elements around a specific element

Using MATLAB, I have a matrix such as:
1 1 0
1 0 1
1 1 1
The aim is to represent the zero's as a mine in a minesweeper program and the values around the 0's should reflect how many mines are adjacent to it.
Therefore creating a vector like this:
1 2 0
1 0 2
1 1 1
I have thought to take elements around the zero as a sub matrix and then add 1, but then it will turn 0's into 1's.
How would I program such a task?
I think this can be achieved by simple convolution plus some post-processing on the resultant matrix as follows:
% Defining a 6x6 matrix of zeros and ones
mineMat=randi(2,6,6)-1;
numberOfMines=conv2(double(~mineMat),ones(3,3),'same').*mineMat;
% Result:
mineMat=
1 0 1 1 0 0
0 0 0 1 0 0
1 1 1 1 1 0
1 1 1 1 0 1
0 1 0 0 0 0
0 1 1 0 0 0
numberOfMines=
3 0 3 3 0 0
0 0 0 3 0 0
2 3 2 3 4 0
1 2 2 4 0 4
0 3 0 0 0 0
0 3 3 0 0 0
Parag's answer would be my first option. Another approach is to use blockproc (Image Processing Toolbox):
blockproc(~M, [1 1], #(x)sum(x.data(:)), 'Bordersize', [1 1], 'TrimBorder', 0).*M
Sounds like you are looking to apply a (two dimensional) filter:
M = [1 1 0; 1 0 1; 1 1 1]==0;
F = filter2(ones(3),M);
F(M)=0
The middle line basically does the work (applying the filter) to create the count. The last line ensures that the mines stay at value 0.

make a delay in my vector, matlab [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have vector for example. Ones and zeros are representing traffic and idle states for base station traffic.
u=[1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 ]
I know how to calculate number of ones and zeros in it after each break.
But I need help for delay. Zeros are telling me when I can put my base station in sleep mode.
Is there a way to make a delay for example that, base station does not go to sleep after first zero, instead of that that it goes to sleep after third zero, that means with some kind o delay.
Not a simple solution but yet I think you should find it interesting. You can optimize from here.
First of all I assumed you wanted to go to sleep after the third consecutive 0.
Check the example.
CODE:
u=[1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 ];
bw_u=bwlabel(u==0);
get_breaks=bsxfun(#eq, bw_u, unique(bw_u)');
pos_break=cumsum(get_breaks,2).*get_breaks;
third_0=pos_break(2:end,:)==3;
[~,indx_third_0]=find(third_0)
OUTPUT:
indx_third_0 =
8
20
32
43
Again assuming ASantosRibeiro interpreted your question correctly, you can do it a little more simply as follows. Let n denote the desired number of zeros. In your case, n=3;
>> ind = find(diff(conv(2*u-1, repmat(-1, [1 n])) == n) == 1) + 1
ind =
8 20 32 43
Assuming ASantosRibeiro interpreted your question correctly, you could do this to find when to "go to sleep":
delay = 3;
idx = find(diff(u)==-1) + delay
idx =
8 20 32 43
This is assuming you want a delay of 3.
diff(u) returns the difference between consecutive elements in u. Finding when the difference equals -1 is equivalent to finding the indices of when the light changes from 1 to 0. By adding the delay, you have your desired indices.

count node degree in matlab from a adjacency matrix

this is my matrix that displays a sample network graph
matrix =
0 1 1 1
1 0 1 0
0 0 0 1
1 1 1 0
where its a 4x4 matrix
1) 2) 3) 4)
1) 0 1 1 1
2) 1 0 1 0
3) 0 0 0 1
4) 1 1 1 0
i want to count this 4x4 matrix like
row 1 counts how many 1s i have and adds column 1 number of 1's to it and returns 1)=5 as total 1's in row 1 and col 1 = 5
i want my output to be like
1=5
2=4
3=4
4=5
This must be it -
out = sum([matrix matrix'],2)
Example run -
matrix =
1 1 1 1
1 0 0 0
0 1 0 1
0 0 1 1
out =
6
3
4
5
The above code would count 1s twice when they appear on the diagonal, which if you don't want, use this -
out1 = sum([matrix matrix'],2) - diag(matrix)
Example run -
matrix =
1 1 1 1
1 0 0 0
0 1 0 1
0 0 1 1
out1 =
5
3
4
4
I agree with the answer of Divakar, but once your graph gets larger and larger, you might not want to transpose the entire matrix. I suggest doing the sum first and then transposing afterwards:
sum(matrix,1)'+sum(matrix,2)-diag(matrix);
matrix =
0 1 1 1
1 0 1 0
0 0 0 1
1 1 1 0
degree=sum(matrix,1)'+sum(matrix,2)-diag(matrix)
degree =
5
4
4
5