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

1 view (last 30 days)
Margarida on 3 Apr 2023
Commented: Margarida on 7 Apr 2023
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:
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!
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>
Margarida on 7 Apr 2023
yes haha i guess you were right

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