Removing Variables From a Cell Array

20 vues (au cours des 30 derniers jours)
Ryan Coder
Ryan Coder le 15 Déc 2022
Modifié(e) : Voss le 15 Déc 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!'}
%%%%%%%%%%

Réponses (2)

Arif Hoq
Arif Hoq le 15 Déc 2022
Modifié(e) : Arif Hoq le 15 Déc 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 commentaire
Ryan Coder
Ryan Coder le 15 Déc 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

Connectez-vous pour commenter.


Voss
Voss le 15 Déc 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]}

Catégories

En savoir plus sur Logical dans Help Center et File Exchange

Produits


Version

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by