segmenting vector with NaN´s [duplicate] - matlab

This question already has answers here:
Finding islands of zeros in a sequence
(6 answers)
Closed 5 years ago.
I have an index vector with NaN's such as:
index=[ 1 2 3 NaN NaN NaN 7 8 9 10 NaN 12 13 14 15 NaN NaN NaN 19 20]
What I want is to obtain in a cell the segments between the NaN's.
So I would want:
segments_index={[1 2 3 ], [ 7 8 9 10], [12 13 14 15], [19 20]};
How to automatically implement this operation?

connected components is one way to do that:
index=[ 1 2 3 NaN NaN NaN 7 8 9 10 NaN 12 13 14 15 NaN NaN NaN 19 20];
notnan = ~isnan(index);
cc = bwconncomp(notnan);
segments_index = cellfun(#(i) index(i),cc.PixelIdxList,'UniformOutput',0)

Related

Search and replace NaN and inf in MATLAB array in the fastest way [duplicate]

This question already has answers here:
Replace values in matrix with other values
(4 answers)
Closed 6 years ago.
Preferably without loop as I can do this with loop and I also suspect it is slow. Maybe?
Say k = [1 1 1 1 3 3 inf 12 3 NaN 13 8 8 8 8 8 NaN 9 9 9];
If the entries of k are NaN or inf, I wish to replace it with 5.
How can I do this?
With isnan and logical indexing:
k = [1 1 1 1 3 3 34 12 3 NaN 13 8 8 8 8 8 NaN 9 9 9];
k( isnan(k) ) = 5;

Row selection with a condition - Matlab

I want to take the rows from the following table (NEW) that the values of the first column of the Edge column (i.e. NEW.Edge(i,1)) are equal to the certain Number (N) and the values in the second column of Edge column (i.e. NEW.Edge(i,2)) are not equal to the values of array (IDs). For example, if N=2 and IDs=15,20 then I should get the rows from 1 to row 9.
The code that I tried so far is :
Y =[];
for i = 1:size(NEW,1)
if ((NEW.Edge(i,1)==N) & (sum(ismember(IDs,NEW.Edge(i,2))==0)))
Y = NEW.Edge(i,1)&NEW.Edge(i,2);
end
end
And
Y = ((NEW.Edge(i,1)==N) & (sum(ismember(IDs,NEW.Edge(i,2))==0)))
Lines = NEW (Y,:)
----Table 'NEW'
Event Node Edge
_________ ____ ________
edgetonew NaN 2 6
edgetonew NaN 2 7
edgetonew NaN 2 8
edgetonew NaN 2 9
edgetonew NaN 2 10
edgetonew NaN 2 11
edgetonew NaN 2 12
edgetonew NaN 2 13
edgetonew NaN 2 14
edgetonew NaN 2 15
edgetonew NaN 15 16
edgetonew NaN 15 17
edgetonew NaN 15 18
edgetonew NaN 15 19
edgetonew NaN 15 20
edgetonew NaN 20 21
You can use ismember and logical indexing to accomplish this. ismember will return a boolean array the size of the first input that is true if each value in the first input is anywhere in the second.
% Will be TRUE when the first column == N and the second column isn't in IDs
rows_to_keep = NEW.Edge(:,1) == N & ~ismember(NEW.Edge(:,2), IDs);
% Now use this logical array to grab just the rows that satisfy the condition
out = NEW(rows_to_keep,:);

Include rows of NaN in matrix at predetermined row numbers.

Initially, I have
Matrix A=
[ 1 2 3
4 255 6
NaN NaN NaN
7 8 9
10 11 12
NaN NaN NaN
10 9 11 ];
I find out the row numbers which are all NaN.
Row_NaN_MatA = [3 6];
After eliminating these rows, I am left with:
Matrix B1 =
[ 1 2 3
4 255 6
7 8 9
10 11 12
10 9 11 ];
After applying a filter, I make the second row of Matrix B = NaN NaN NaN. Therefore
Matrix B2 =
[ 1 2 3
NaN NaN NaN
7 8 9
10 11 12
10 9 11 ];
Now, the question is, after all these processing, I want to get the initial matrix back, but with all the deleted elements as NaN. So the required output I want is:
Output Matrix=
[ 1 2 3
NaN NaN NaN
NaN NaN NaN
7 8 9
10 11 12
NaN NaN NaN
10 9 11 ];
I know the dimensions of output I want (= initial Matrix A dimensions), and the row numbers which should be NaN (= Row_NaN_MatA) . The rest of the rows should be equal to rows of Matrix B2.
How can I do this?
Use setdiff to get the row IDs that were not part of Row_NaN_MatA by setdiff-ing Row_NaN_MatA with the a 1D array of indices for the entire row extent of A, like so -
output = A
output(setdiff(1:size(A,1),Row_NaN_MatA),:) = B2
You can also use ismember for the same effect -
output(~ismember(1:size(A,1),Row_NaN_MatA),:) = B2
Or use bsxfun there -
output(all(bsxfun(#ne,Row_NaN_MatA(:),1:size(A,1))),:) = B2
Sample run -
>> A
A =
1 2 3
4 255 6
NaN NaN NaN
7 8 9
10 11 12
NaN NaN NaN
10 9 11
>> B1
B1 =
1 2 3
4 255 6
7 8 9
10 11 12
10 9 11
>> B2
B2 =
1 2 3
NaN NaN NaN
7 8 9
10 11 12
10 9 11
>> output
output =
1 2 3
NaN NaN NaN
NaN NaN NaN
7 8 9
10 11 12
NaN NaN NaN
10 9 11

Concatenate matrices with different start index and different end index (Aligning)

for i = 1 : numel(T);
j = 1 : numel(T(i).n);
P(i,j) = (T(i).n);
G(i) = (T(i).lastPulse)-1100;
Y = P(1,G(1):length(T(1).n));
S = P(2,G(2):length(T(2).n));
end
I have the preceeding code. P is a (191x10000) matrix. I want to take out a specific portion of each row as I showed in S and Y and then concatenate S and Y and other row matrices corresponding to other rows of P to create matrix A(191x[max length of (S,Y,...)]). BUT the tricky part is that I cannot make S and Y aligned.
EXAMPLE:
P = [1 2 1 3 1 1 1 0 3 1 0]
[3 0 2 0 1 1 4 1 1 2 0];
S = P(1,1:7) = [1 2 1 3 1 1 1];
Y = P(2,5:10) = [1 1 4 1 1 2];
% A = concatenated S and Y aligned to original P.
A = [ 1 2 1 3 1 1 1 nan nan nan nan]
[nan nan nan nan 1 1 4 1 1 2 nan];
Preferably I would like to use a loop instead of separated matrices such as S and Y since I have many rows.
Suggested Answer:
I have the idea that probably I have to use indices corresponding to P and use them to concatenate Y and S, I just don't know how to execute this thought especially in a loop.
If I got the question correctly in my head, it seems bsxfun could be used here for creating a mask and then keep the masked elements from P and thus have an aligned output. Here's an implementation to go along those lines -
%// Random input array
P = randi(9,5,11)
%// Define the start and stop(end) indices as vectors
start_idx = [1 5 3 4 11]
stop_idx = [7 10 3 6 11]
%// Get the size of P and initialize output array
[M,N] = size(P);
P_out = NaN(M,N);
%// Create the mask for extracting specific elements from P
mask = bsxfun(#le,start_idx(:),1:N) & bsxfun(#ge,stop_idx(:),1:N);
%// Put masked elements from P into output array
P_out(mask) = P(mask)
Another way to get the output without initializing it, would be like this -
P_out = P.*mask;
P_out(~mask) = NaN;
So, to correlate with the variables used in the question, start_idx would be G and stop_idx would be [length(T(1).n),length(T(2).n).length(T(3).n),...].
Sample run -
P =
1 6 8 8 8 1 9 1 2 4 2
8 8 6 3 7 6 7 2 5 1 2
6 8 9 5 6 6 6 8 6 5 2
9 9 5 9 3 7 9 5 1 2 1
7 1 5 6 6 9 6 8 6 2 6
start_idx =
1 5 3 4 11
stop_idx =
7 10 3 6 11
P_out =
1 6 8 8 8 1 9 NaN NaN NaN NaN
NaN NaN NaN NaN 7 6 7 2 5 1 NaN
NaN NaN 9 NaN NaN NaN NaN NaN NaN NaN NaN
NaN NaN NaN 9 3 7 NaN NaN NaN NaN NaN
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 6

Matlab : backtrack path from matrices

I have a data :
minval = NaN 7 8 9 9 9 10 10 10 10
NaN NaN 10 10 10 10 10 10 10 10
NaN NaN NaN 10 10 9 10 10 10 9
NaN NaN NaN NaN 9 9 10 9 10 10
NaN NaN NaN NaN NaN 9 10 10 10 10
NaN NaN NaN NaN NaN NaN 10 11 10 10
NaN NaN NaN NaN NaN NaN NaN 10 10 10
NaN NaN NaN NaN NaN NaN NaN NaN 10 10
NaN NaN NaN NaN NaN NaN NaN NaN NaN 10
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
and I do this following :
C=size(minval,2);
D1(1,2:end) = minval(1,2:C);
D2 = bsxfun(#plus,minval(2:C-1,3:C),D1(1,1:C-2)');
D2 = [zeros(1,size(D2,2)) ;D2];
D2(D2==0) = NaN;
D1(2,3:end) = nanmin(D2);
D3 = bsxfun(#plus,minval(3:C-1,4:C),D1(2,2:C-2)');
D3 = [zeros(2,size(D3,2)) ;D3];
D3(D3==0) = NaN;
D1(3,4:end)= nanmin(D3);
Then, I want to backtrack the path which D1(end,end)comes from.
Is there any help? Thank you.
In MATLAB you can index out parts of matrices directly. There's no need for loops here:
C=size(minval,2);
D1(2:C) = minval(1,2:C);
For these ones you are not doing what you hoped, I suspect:
for e=3:C
for b=2:e-1
D2(e)=min(minval(b,e)+D1(b-1));
end
end
In the inner loop, for each value of b (from 2 to e-1), you are overwriting the value of D2 at each step. Only the result for the last value of b will be recorded. There may well be a much simpler way of getting the result you want. min and other functions do not just work on two single values but on entire matrices - e.g. you can do:
min(minval)
ans =
NaN 7 8 9 9 9 10 9 10 9