Replacing NaNs with zero in a matrix within a cell array.
29 ビュー (過去 30 日間)
古いコメントを表示
How to replace NaNs with 0 in a cell array that has the following anatomy 13x1 cell, Each cell is of size 63x63[double]. the cell name is 'a'.
Any help would be appreciated, Thank you in advance.
2 件のコメント
採用された回答
Walter Roberson
2019 年 1 月 22 日
a = cellfun(@(M) subsasgn(M, substruct('()', {isnan(M)}), 0), a, 'uniform', 0);
No loop needed... just ugly code.
3 件のコメント
James Spalding
2022 年 10 月 19 日
Hi Guys, I have a similiar problem but am getting errors prior to running from subsasgn:
"output must be assigned to a variable"
and after running get :
"Error using cellfun
Non-scalar in Uniform output, at index 1, output 1.
Set 'UniformOutput' to false."
I think it might be i don't understand the "M" variable which is used in the above solution. I've attached my cell variable {17x1} with uniform 362x292 matrices, also of note I am replacing the NaNs with a meaningless large number. I have tried switiching around M a destination variable as well as the call variable with NaNs.
I've attached the cell vairable and the code is below.
Any help here is greatly appreciated!
RvarNnan1 = cellfun(@(M) subsasgn(M, substruct('()', {isnan(M)}), 123000), RvarNnan1, 'UniformOutput', 123000);
Walter Roberson
2022 年 10 月 21 日
@James Spalding The number after the keyword 'UniformOutput' is treated as a logical switch. It is tested for being either 0 (meaning No, Not uniform output) or non-zero (meaning Yes, uniform output). So when you changed from 'UniformOutput', 0 (not uniform output) to 'UniformOutput', 123000 you were switching to "yes, uniform output". Which is not correct for this situation.
The M variable is a "dummy parameter".
a = cellfun(@(M) subsasgn(M, substruct('()', {isnan(M)}), 0), a, 'uniform', 0);
means that each entry inside the cell named a is to be processed, with the content of each cell passed in turn as the first parameter to the anonymous function
@(M) subsasgn(M, substruct('()', {isnan(M)}), 0)
That anonymous function definition means that each time the anonymous function is executed, that a single parameter is to be accepted as input, and that everywhere inside the body of the code that the name M occurs it is to be replaced with what was passed in. The function handle is almost exactly equivalent to
@(varargin) subsasgn(varargin{1}, substruct('()', {isnan(varargin{1})}), 0)
-- that is, that the name of the variable M is not relevant (in nearly all conditions), that what is important is that it is the first parameter passed in that is being referred to, and what was passed in to the anonymous function is to be passed to first isnan() and later subsasgn() .
The reasons it is not exactly equivalent: (A) the @(varargin) version accepts extra parameters whereas the @(M) version errors if extra parameters are passed to the function; and (B) in the case where a named parameter is used, if a function is called that uses inputname then the name of the dummy parameter M can be retrieved, whereas if varargin is used, inputname() will return empty.
Functionally a = cellfun(@(M) subsasgn(M, substruct('()', {isnan(M)}), 0), a, 'uniform', 0); is equivalent to
if exist('M', 'var')
SomeTemporaryInternalVariableName = M;
SomeOtherTemporaryInternalVariableName = true;
else
SomeOtherTemporaryInternalVariableName = false;
end
a = cell(size(a));
for K = 1 : numel(a)
M = a{K};
M = subsasgn(M, substruct('()', {isnan(M)}, 0);
a{K} = M;
end
if SomeOtherTemporaryInternalVariableName
M = SomeTemporaryInternalVariableName;
clear SomeTemporaryInternalVariableName
end
clear SomeOtherTemporaryInternalVariableName
which is to say, that the name M is used temporarily to hold the element during the calculation, and afterwards if M existed already, M is restored to its previous value.
M is not the name of the variable you are trying to work with.
The adjusted code for you should be
RvarNnan1 = cellfun(@(M) subsasgn(M, substruct('()', {isnan(M)}), 123000), RvarNnan1, 'UniformOutput', 0);
but you should consider instead doing
RvarNnan1 = cellfun(@(M) fillmissing(M, 'constant', 123000), RvarNnan1, 'UniformOutput', 0);
as suggested by @Andy Campbell
その他の回答 (2 件)
Omer Yasin Birey
2019 年 1 月 22 日
編集済み: Omer Yasin Birey
2019 年 1 月 22 日
% a = cell(13,1);
% %initializing the values
% for i = 1:length(a)
% a{i} = nan(63,63);
% end
%removing the nans
for k = 1:size(a,1)
for j = 1:size(a,2)
a{k,j}(isnan(a{k,j}))=0;
end
end
Andy Campbell
2019 年 3 月 1 日
編集済み: Andy Campbell
2019 年 3 月 1 日
The fillmissing function is built for this, you just need to use cellfun since each of these doubles are included in the cell array.
nanless = cellfun(@(c) fillmissing(c,'constant',0), a,'UniformOutput',false)
If you don't want to use cellfun, since it looks like you data is all uniform you can also do this by putting each cell into an array, applyin fillmissing, and then reshaping it back into the cell array:
array = [a{:}]; % This works because they are all 63x63
array = fillmissing(array,'constant',0);
a = mat2cell(array, 63, ones(1,13)*63)
and of course this can all be one-lined
a = mat2cell(fillmissing([a{:}],'constant',0), 63, ones(1,13)*63);
0 件のコメント
参考
カテゴリ
Help Center および File Exchange で Line Plots についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!