Matlab Trimming at Bounds
-
29-10-2019 - |
Question
I have a matrix A:
NaN NaN NaN NaN NaN NaN NaN 10 1 8 7 2 5 6 2 3 49 NaN NaN NaN NaN NaN NaN
I was wondering if there was a way to detect when the NaNs first turn to numbers and turn the 1st 2 points to NaNs, such as the 10 & 1 both to NaN.
Then find when the numbers turn to NaNs and turn the last two number points, 3 and 49 to NaNs.
Originally I was thinking of using the following, but I was wondering if this was the best way:
i= 2;
while i < 1440
if isnan(A(i)) < isnan(A(i-1)) //Transitioning from NaN to numbers
A(i:i+2) = NaN;
i = i+ 4;
elseif isnan(A(i)) > isnan(A(i-1)) //Transitioning from numbers to NaNs
A(i-2:i) = NaN;
i = i + 1;
else
i = i + 1;
end
end
but was wondering if there was any other way I could optimize it?
Solution
First I assume that your vector A is organized with NaN's at the start and end and a continous set of numerics in the middle, as in
A = [NaN ... NaN, contiguous numeric data, NaN ... NaN]
First, I suggest locating the numeric data and working from there, as in,
flagNumeric = ~isnan(A);
Now flagNumeric will be a true for the entries that are numeric and false for NaN's.
So the first numeric will be at
firstIndex = find(flagNumeric,1,'first');
and the last numeric at
lastIndex = find(flagNumeric,1,'last');
You can then use firstIndex and lastIndex to change the first and last numeric data to NaN's
A(firstIndex:firstIndex+1) = NaN;
A(lastIndex-1:lastIndex) = NaN;
OTHER TIPS
% Set the first two non-NaN numbers to NaN
first = find(isfinite(A), 1, 'first');
A(first:first+1) = NaN;
% Set the last two non-NaN numbers to NaN
last = find(isfinite(A), 1, 'last');
A(last-1:last) = NaN;
Of course, the above code will break in special cases (e.g. when last == 1
), but these should be straightforward to filter out.
Here's a slightly simpler version based on the same assumption as Azim's answer:
nums = find(~isnan(A));
A( nums([1 2 end-1 end]) ) = NaN;