Removing Variables From a Cell Array
21 views (last 30 days)
Show older comments
Hey guys! I am having trouble modifying these cell arrays to remove any NaN, string, or complex variables. Ive tried a few different versions of removing NaN, but it doesnt work on the cell array X, and then for the array Y it wont remove the final string. Something I'm missing?
%%%%%%%%%%%%%%%%
clc; clear all; close all;
% This script removes all NaN entires, strings, and complex values using a
% for loop and creates a mesh plot of a function over the rang of data for
% x and y.
% 20 points for x and y
% x y z labels + title and set color transition to interpolated
x = {2 4 3+5*i NaN 6 9.8 'Hello' 11 -3 -4+6*i};
y = {NaN NaN -7 8 0 4.5 i 15 'how are you?' 'fine, tnx!'};
%%%% FILTER X %%%%
n = length(x);
for ii = 1:n
%disp(isnan(x{ii})); %%%%
%disp(n) %%%%
%disp(length(x)) %%%%
if (ii > length(x))
break;
end
switch true
case (isstr(x{ii}) )
x(ii) = [];
ii = ii-1;
n = n-1;
case (~isreal(x{ii}) )
x(ii) = [];
ii = ii-1;
n = n-1;
case (isnan(x{ii}) )
disp(isnan(x{ii})) %%%%
x(cellfun(@(x) any(isnan(x)),x) ) = [];
ii = ii-1;
n = n-1;
end
%disp(x) %%%%
%disp(ii) %%%%
end
%%%% FILTER Y %%%%
for ii = 1:n
if (ii > length(y))
break;
end
switch true
case (isstr(y{ii}) )
y(ii) = [];
ii = ii-1;
n = n-1;
case (~isreal(y{ii}) )
y(ii) = [];
ii = ii-1;
n = n-1;
case (isnan(y{ii}) )
disp(isnan(y{ii})) %%%%
y(cellfun(@(y) any(isnan(y)),y) ) = [];
ii = ii-1;
n = n-1;
end
end
disp(x)
disp(y)
%%%%%%%%%%
0 Comments
Answers (2)
Voss
on 15 Dec 2022
"for the array Y it wont remove the final string"
That's because changing the loop iterator (in this case the variable ii) doesn't do what you think it does.
Consider this simple loop:
for ii = 1:3
disp(ii);
ii = ii-1;
end
Should it run forever? In fact it iterates three times. Decreasing ii by 1 changes ii for the remainder of the current iteration, but at the start of the next iteration ii takes the value it would have if you hadn't changed it at all.
So when you do ii = ii-1 with the expectation that the iith iteration will repeat again, it does not, and you end up skipping some elements of x or y.
See the output below. The -7 is never checked because the two NaNs are both removed in the first iteration, so on the second iteration ii is 2 and y{2} is 8. Similarly the 15 and the 'fine, tnx!' are never checked because of the removal of elements just before them.
y = {NaN NaN -7 8 0 4.5 i 15 'how are you?' 'fine, tnx!'};
n = length(y);
%%%% FILTER Y %%%%
for ii = 1:n
fprintf('ii = %02d: length(y) is %02d\n',ii,length(y));
if (ii > length(y))
disp('done.');
break;
end
fprintf('current y{ii}:');
disp(y{ii});
switch true
case (isstr(y{ii}) )
y(ii) = [];
ii = ii-1;
n = n-1;
case (~isreal(y{ii}) )
y(ii) = [];
ii = ii-1;
n = n-1;
case (isnan(y{ii}) )
% disp(isnan(y{ii})) %%%%
y(cellfun(@(y) any(isnan(y)),y) ) = [];
ii = ii-1;
n = n-1;
end
end
disp(y)
The correct way to iterate along a vector when you may be changing the length of the vector as you go is to use a while loop, and it can be made to work as you intended:
y = {NaN NaN -7 8 0 4.5 i 15 'how are you?' 'fine, tnx!'};
n = length(y);
%%%% FILTER Y %%%%
ii = 1;
while ii <= length(y)
fprintf('ii = %02d: length(y) is %02d\n',ii,length(y));
fprintf('current y{ii}:');
disp(y{ii});
switch true
case (isstr(y{ii}) )
y(ii) = [];
case (~isreal(y{ii}) )
y(ii) = [];
case (isnan(y{ii}) )
% disp(isnan(y{ii})) %%%%
y(cellfun(@(y) any(isnan(y)),y)) = [];
otherwise
ii = ii+1;
end
end
disp(y)
However, it's not necessary to use a loop at all:
y = {NaN NaN -7 8 0 4.5 i 15 'how are you?' 'fine, tnx!'};
y(cellfun(@(y)isstr(y) || ~isreal(y) || isnan(y), y)) = [];
disp(y);
But note that isstr is not recommended - use ischar instead.
Also, note that if you want to handle the case that y has some cells that contain non-scalar numeric arrays and you want to remove those cells if their contents contain any NaN (I imagine this was your intent with using any(isnan(y))) you should use any(isnan(y,'all')) or any(isnan(y(:)) because any operates down columns for matrix inputs. For example:
y = {NaN(3,2)} % a single cell containing a matrix of NaNs
y(cellfun(@(y) any(isnan(y),'all'),y)) = [] % any() of the whole matrix
y = {NaN(3,2)} % again
y(cellfun(@(y) any(isnan(y(:))),y)) = [] % (:) converts it to a column vector first
y = {NaN(3,2)} % again
try
cellfun(@(y) any(isnan(y)),y) % error: any(isnan(y{1})) is the 1-by-2 array [true true] in this case
catch err
disp(err.message)
end
Finally,
y = {NaN NaN -7 8 0 4.5 i 15 'how are you?' 'fine, tnx!'};
y(cellfun(@(y)ischar(y) || ~isreal(y) || any(isnan(y),'all'), y)) = [];
disp(y)
0 Comments
See Also
Categories
Find more on Logical in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!