Matrix processing problem; creating new matrix

Hi,
I have the following experimental set up. An object is able to move between three areas (A, B and C). It can only access C via B.
I am interested in knowing at what point the object moved from C to B, and then whether it moved onto A or back to C.
i.e. if the data matrix looked like the following:
0 0 0
0 0 1
0 1 0
0 1 0
1 0 0
0 1 0
0 1 0
0 0 1
0 1 0
0 0 1
0 0 1
0 0 0
I would want to output a new matrix:
0
0
1 (marking C to B transition)
0
2 (marking B to A transition, following a C to B transition)
0
0
0
1 (marking C to B transition)
3 (marking B to C transition, following a C to B transition)
0
0
I already have the following code to mark transitions from C to B:
matrix =[0 0; 0 1; 1 0; 0 1; 0 1; 0 1; 1 0]; % column 1 = B, column 2 = C
if matrix(1,1)
output1 = nan;
else
output1 = 0;
end
output2end = matrix(2:end,1) & matrix(1:end-1,2);
output_Cage1 = [output1; output2end];
output_Cage1 =
0
0
1
0
0
0
1
But I am not sure how to extend this to work for 3 columns. Any help would be much appreciated. Many thanks.

 Accepted Answer

matrix = [0 0 0
0 0 1
0 1 0
0 1 0
1 0 0
0 1 0
0 1 0
0 0 1
0 1 0
0 0 1
0 0 1
0 0 0];
if matrix(1,1)
output1 = nan;
else
output1 = 0;
end
output2end = matrix(2:end,2) & matrix(1:end-1,3);
output_Cage1 = [output1; output2end] % C to B
output_Cage1 = 12×1
0 0 1 0 0 0 0 0 1 0
% Identify all B to A
output2end = matrix(2:end,1) & matrix(1:end-1,2);
output_Cage2 = output_Cage1+[output1; 2*output2end] % B to A
output_Cage2 = 12×1
0 0 1 0 2 0 0 0 1 0
% Identify all B to C
output2end = matrix(2:end,3) & matrix(1:end-1,2);
output_Cage3 = output_Cage2+[output1; 3*output2end] % B to C
output_Cage3 = 12×1
0 0 1 0 2 0 0 3 1 3
% Remove B to C or B to A that does not follow C to B
for ii = 1:length(output_Cage3) % iteratively go through array
if output_Cage3(ii) == 1 % if C to B happens, then set count to 1
count = 1;
elseif output_Cage3(ii) ~= 0 % if the value is not 0 or 1
if count == 0 % and count is 0 (no previous C to B detected)
output_Cage3(ii) = 0; % then remove the B to C or B to A present
end
count = 0; % set count back to 0 indicating that there is no previous C to B.
end
end
output_Cage3
output_Cage3 = 12×1
0 0 1 0 2 0 0 0 1 3

16 Comments

Hi Kevin,
That's brilliant, thank you so much!
Are you able to add a few further comments to the code, as I am not sure I totally understand what each line is doing?
Many thanks :)
I added some comments. Let me know if it still isn't clear. If you are happy with the answer, please accept it. Thanks.
Hi Kevin,
Thanks for adding the comments. The code works on the example matrix, however, when I run it with my data I am getting values of up to 6 in the output_Cage3. Do you have any ideas?
Many thanks
Did you change output2end?
Seems like some point are labeled as all three possibilities B to C, B to A, and C to B. 2+3+1 = 6.
No, I didn't change output2end. But I think you're right - some points are being labelled as 2, or all 3, of the possibilities. I have taken a closer look at my data, and it seems that in some time bins, more than 1 sensor is being activated as the object moves between sections.
So actually, the example matrix should look more like:
0 0 1
0 1 1
1 1 1
1 1 0
0 1 0
0 1 1
0 0 1
0 1 1
0 1 1
0 0 1
0 0 0
And the output I would like would be:
0
1
2
0
0
0
0
1
0
3
0
But with the current code, the output I get is:
0
1
6
0
0
0
0
1
4
0
0
Why would you consider the 3 row as going from B to A (2)? How do you want to handle the data if all 3 sensors are active? Below I ignore rows when more than one channel was active.
matrix = [0 0 1
0 1 1
1 1 1
1 1 0
0 1 0
0 1 1
0 0 1
0 1 1
0 1 1
0 0 1
0 0 0];
if matrix(1,1)
output1 = nan;
else
output1 = 0;
end
output2end = matrix(2:end,2) & matrix(1:end-1,3);
output_Cage1 = [output1; output2end] % C to B
output_Cage1 = 11×1
0 1 1 1 0 0 0 1 1 0
% Identify all B to A
output2end = matrix(2:end,1) & matrix(1:end-1,2);
output_Cage2 = output_Cage1+[output1; 2*output2end]; % B to A
output_Cage2(output_Cage2>2)=0
output_Cage2 = 11×1
0 1 0 0 0 0 0 1 1 0
% Identify all B to C
output2end = matrix(2:end,3) & matrix(1:end-1,2);
output_Cage3 = output_Cage2+[output1; 3*output2end]; % B to C
output_Cage3(output_Cage3>3)=0
output_Cage3 = 11×1
0 1 3 0 0 3 3 1 0 3
% Remove B to C or B to A that does not follow C to B
for ii = 1:length(output_Cage3) % iteratively go through array
if output_Cage3(ii) == 1 % if C to B happens, then set count to 1
count = 1;
elseif output_Cage3(ii) ~= 0 % if the value is not 0 or 1
if count == 0 % and count is 0 (no previous C to B detected)
output_Cage3(ii) = 0; % then remove the B to C or B to A present
end
count = 0; % set count back to 0 indicating that there is no previous C to B.
end
end
output_Cage3
output_Cage3 = 11×1
0 1 3 0 0 0 0 1 0 3
Hi Kevin,
Thanks for your response, and apologies for the added complexity.
I think the easiest way would be to process the data first so that only one sensor is active on any one row, and then once processed, run it through the code above.
The raw data is not actually just 0 and 1s, it goes from 0 to 100. So perhaps I could scan through the data, and for each row just create a new matrix with a "1" in the highest value column.
i.e.
83 91 31
72 58 95
0 90 0
0 100 16
would become:
0 1 0
0 0 1
0 1 0
0 1 0
If the values in any two rows are the same, then just assign a 1 to the column that was previously active.
Then I could run this new matrix through the code above, and hopefully avoid any issues.
What do you think?
Many thanks again :)
That sounds like a good plan. Here is some help:
test = 100*rand(8,3)
test = 8×3
6.3456 25.3372 35.5083 12.0295 87.9503 46.9517 12.3997 79.0664 39.8260 99.3375 96.9943 0.7258 25.7053 6.6752 60.0746 75.9362 47.8973 25.7890 42.5690 19.2425 86.3008 73.9219 29.4729 35.6253
[maxvalues, index] = max(test');
New = zeros(size(test));
for ii = 1:length(New)
New(ii,index(ii))=1;
end
New
New = 8×3
0 0 1 0 1 0 0 1 0 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0
Brilliant, thanks for your help :)
Hi Kevin,
Unfortunately selecting the highest value sensor didn't work as planned. However, I know what I need to do:
I would like to scan through my data matrix rows and create a new matrix based on the following rules:
  1. If all columns are 0, assign three 0s to the new matrix.
  2. If all columns are 1, assign a 1 to column 2 of the new matrix and a 0 to column 1 and 3.
  3. If 2 columns =1, move up rows until you hit a 0 in at least one of those rows and assign a 1 to this column and a 0 to the other column.
  4. (If you hit a 0 at the same time, then assign a 1 to both columns) and continue.
My plan is to run this loop twice so that even if point 4. occurs, once I run it twice, this should not be a problem.
e.g. original matrix = [1 0 0; 1 1 0; 1 0 0; 1 0 0; 1 1 1; 0 1 1; 0 1 1; 1 1 1; 1 1 0; 1 1 0; 1 0 0; 1 1 0; 1 0 0]
Should turn into, after one round of data processing:
[1 0 0; 0 1 0; 1 0 0; 1 0 0; 0 1 0; 0 1 1; 0 1 1; 0 1 0; 1 0 0; 1 0 0; 1 0 0; 0 1 0; 1 0 0]
and after two rounds:
[1 0 0; 0 1 0; 1 0 0; 1 0 0; 0 1 0; 0 0 1; 0 0 1; 0 1 0; 1 0 0; 1 0 0; 1 0 0; 0 1 0; 1 0 0]
If there is a way to put this all into one function, that would be brilliant. If you were able to direct me to some resources on if/else loops that would be much appreciated as I know what I want to achieve, but am not sure how to assign new values to new matrices based on an original matrix.
Many thanks again,
Laura
x2 =[1 0 0; 0 1 0; 1 0 0; 1 0 0; 0 1 0; 0 1 1; 0 1 1; 0 1 0; 1 0 0; 1 0 0; 1 0 0; 0 1 0; 1 0 0];
x3= [1 0 0; 0 1 0; 1 0 0; 1 0 0; 0 1 0; 0 0 1; 0 0 1; 0 1 0; 1 0 0; 1 0 0; 1 0 0; 0 1 0; 1 0 0];
x = [1 0 0; 1 1 0; 1 0 0; 1 0 0; 1 1 1; 0 1 1; 0 1 1; 1 1 1; 1 1 0; 1 1 0; 1 0 0; 1 1 0; 1 0 0]
x = 13×3
1 0 0 1 1 0 1 0 0 1 0 0 1 1 1 0 1 1 0 1 1 1 1 1 1 1 0 1 1 0
newx = insertfunctionname(x)
newx = 13×3
1 0 0 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0
newx2 = insertfunctionname(newx)
newx2 = 13×3
1 0 0 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0
function [newx] = insertfunctionname(x)
newx = zeros(size(x)); % If all columns are 0, assign three 0s to the new matrix.
for ii = 1:size(x,1)
if sum(x(ii,:)) == 1
newx(ii,:) = x(ii,:);
elseif sum(x(ii,:)) == 3
newx(ii,2) = 1; %If all columns are 1, assign a 1 to column 2 of the new matrix and a 0 to column 1 and 3.
elseif sum(x(ii,:)) == 2 %If 2 columns =1,
index = find(x(ii,:)==1);
for iii = ii+1:size(x,1) %move up rows
if sum(x(iii,index))<2 %until you hit a 0 in at least one of those rows
newx(ii,index) = x(iii,index)==0; %and assign a 1 to this column and a 0 to the other column.
break
end
end
end
end
end
Hi Kevin,
This is perfect - thank you SO much!
Hi Kevin,
When running the code below, with some of my datasets it works perfectly, but then with others (of the same format) it comes up with this error. Do you have any ideas as to why this might be? Many thanks!
It looks like it is treating count as a function. Do you have a function called count? If so and if it is needed, you can rename the count variable to something else.
Ah, I see, thanks. I do not have a function called count, but I hadn't created a variable called "count" prior to the loop. When I create count before hand, it then runs properly. I am assuming I should set count to 0 when I define it? Many thanks!

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!