Removing Variables From a Cell Array

21 views (last 30 days)
Ryan Coder
Ryan Coder on 15 Dec 2022
Edited: Voss on 15 Dec 2022
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
1
disp(x)
{[2]} {[4]} {[NaN]} {[6]} {[9.8000]} {[11]} {[-3]}
disp(y)
{[-7]} {[8]} {[0]} {[4.5000]} {[15]} {'fine, tnx!'}
%%%%%%%%%%

Answers (2)

Arif Hoq
Arif Hoq on 15 Dec 2022
Edited: Arif Hoq on 15 Dec 2022
x = {2 4 3+5*1i NaN 6 9.8 'Hello' 11 -3 -4+6*1i};
x(cellfun(@(x) any(isnan(x)),x)) = []
x = 1×9 cell array
{[2]} {[4]} {[3.0000 + 5.0000i]} {[6]} {[9.8000]} {'Hello'} {[11]} {[-3]} {[-4.0000 + 6.0000i]}
y = {NaN NaN -7 8 0 4.5 1i 15 'how are you?' 'fine, tnx!'};
y(strncmp(y,'fine, tnx!',4)) = []
y = 1×9 cell array
{[NaN]} {[NaN]} {[-7]} {[8]} {[0]} {[4.5000]} {[0.0000 + 1.0000i]} {[15]} {'how are you?'}
  1 Comment
Ryan Coder
Ryan Coder on 15 Dec 2022
For the string, is there an error in my for loop that could be fixed so that line is unecessary? Id like it to work for all sets of data not just that specific string

Sign in to comment.


Voss
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
1 2 3
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
ii = 01: length(y) is 10
current y{ii}:
NaN
ii = 02: length(y) is 08
current y{ii}:
8
ii = 03: length(y) is 08
current y{ii}:
0
ii = 04: length(y) is 08
current y{ii}:
4.5000
ii = 05: length(y) is 08
current y{ii}:
0.0000 + 1.0000i
ii = 06: length(y) is 07
current y{ii}:
how are you?
ii = 07: length(y) is 06
done.
disp(y)
{[-7]} {[8]} {[0]} {[4.5000]} {[15]} {'fine, tnx!'}
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
ii = 01: length(y) is 10
current y{ii}:
NaN
ii = 01: length(y) is 08
current y{ii}:
-7
ii = 02: length(y) is 08
current y{ii}:
8
ii = 03: length(y) is 08
current y{ii}:
0
ii = 04: length(y) is 08
current y{ii}:
4.5000
ii = 05: length(y) is 08
current y{ii}:
0.0000 + 1.0000i
ii = 05: length(y) is 07
current y{ii}:
15
ii = 06: length(y) is 07
current y{ii}:
how are you?
ii = 06: length(y) is 06
current y{ii}:
fine, tnx!
disp(y)
{[-7]} {[8]} {[0]} {[4.5000]} {[15]}
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);
{[-7]} {[8]} {[0]} {[4.5000]} {[15]}
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 = 1×1 cell array
{3×2 double}
y(cellfun(@(y) any(isnan(y),'all'),y)) = [] % any() of the whole matrix
y = 1×0 empty cell array
y = {NaN(3,2)} % again
y = 1×1 cell array
{3×2 double}
y(cellfun(@(y) any(isnan(y(:))),y)) = [] % (:) converts it to a column vector first
y = 1×0 empty cell array
y = {NaN(3,2)} % again
y = 1×1 cell array
{3×2 double}
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
Non-scalar in Uniform output, at index 1, output 1. Set 'UniformOutput' to false.
See the documentation for any.
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)
{[-7]} {[8]} {[0]} {[4.5000]} {[15]}

Products


Release

R2022a

Community Treasure Hunt

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

Start Hunting!