How to fill zeros and NaNs with the average of the previous nonzero consecutive values (part 2)

2 views (last 30 days)
Hi, here's a challenge that is too hard for me and I need enlightment, a few weeks ago I posted this question:
"So, i have a column like this:
T = [0;0;1;2;3;4;NaN;4;3;0;0;0;NaN;4;2;3;0;2;0];
And everytime I have a NaN or a zero, I would like to transform them in the average of the previous nonzero consecutive values (averages in bold):
T = [0;0;1;2;3;4;2.5;4;3;3.5;3.5;3.5;3.5;4;2;3;3;2;2];
I cannot figure out how I can do this in an efficient way (without for loops, because the column has thousands of rows)."
This was the only answer I got which helped me a lot:
"Using this FEX download,
T = [0;0;1;2;3;4;NaN;4;3;0;0;0;NaN;4;2;3;0;2;0];
idx=find(T,1);
[stem,T]=deal(T(1:idx-1),T(idx:end));
G=groupTrue(~isnan(T) & T~=0);
[~,~,lengths]=groupLims(groupTrue(~G),1);
T(~G)=repelem( groupFcn(@mean,T,G) ,lengths);
T=[stem;T]
T'
"
However, I think sometime my data has too many NaNs or zeros and I get erros like this:
Error using splitapply
Group numbers must be a vector of positive integers, and cannot be a sparse vector.
Error in groupFcn (line 30)
[varargout{1:nargout}]=splitapply(func,varargin{:},G);
Error in PowerDependency (line 130)
T(~G)=repelem( groupFcn(@mean,T,G) ,lengths);
Making me think that it's risky to use these types of functions that I can't understand when I have errors (lol).
Anyways my help request is can anyone figure out another way? Doesn't have to be duper efficient and instant, I can handle a few seconds of run time, but not too much like verifying row by row :(
I would be extremely happy if someone could help, cheers!
  14 Comments
dpb
dpb on 6 Apr 2023
My first foray into the fray in response to "I think sometime my data has too many NaNs or zeros and I get erros like this..." was to observe that
:I'd venture it's not enough, rather than too many. If there were an empty result that would produce the message."
"Just sayin..." <vbg>

Sign in to comment.

Answers (1)

Peter Perkins
Peter Perkins on 6 Apr 2023
Just for fun: a varfun soln. Would look similar using grouptransform.
Step one is to define groups of elements by finding runs of non-NaN/non-zero followed by runs of NaN/zero.
x = [0;0;1;2;3;4;NaN;4;3;0;0;0;NaN;4;2;3;0;2;0];
x(x == 0) = NaN;
i = isnan(x);
starts = [false; diff(i) < 0];
group = cumsum(starts);
T = table(x,i,starts,group)
T = 19×4 table
x i starts group ___ _____ ______ _____ NaN true false 0 NaN true false 0 1 false true 1 2 false false 1 3 false false 1 4 false false 1 NaN true false 1 4 false true 2 3 false false 2 NaN true false 2 NaN true false 2 NaN true false 2 NaN true false 2 4 false true 3 2 false false 3 3 false false 3
Step 2 is to replace NaNs with the group means.
T2 = varfun(@myFun,T,InputVariables="x",GroupIngVariable="group")
T2 = 19×3 table
group GroupCount myFun_x _____ __________ _______ 0 2 NaN 0 2 NaN 1 5 1 1 5 2 1 5 3 1 5 4 1 5 2.5 2 6 4 2 6 3 2 6 3.5 2 6 3.5 2 6 3.5 2 6 3.5 3 4 4 3 4 2 3 4 3
T.xFilled = T2.myFun_x
T = 19×5 table
x i starts group xFilled ___ _____ ______ _____ _______ NaN true false 0 NaN NaN true false 0 NaN 1 false true 1 1 2 false false 1 2 3 false false 1 3 4 false false 1 4 NaN true false 1 2.5 4 false true 2 4 3 false false 2 3 NaN true false 2 3.5 NaN true false 2 3.5 NaN true false 2 3.5 NaN true false 2 3.5 4 false true 3 4 2 false false 3 2 3 false false 3 3
function x = myFun(x)
m = mean(x,"omitmissing");
x(isnan(x)) = m;
end

Categories

Find more on Loops and Conditional Statements 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!