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

3 次查看(过去 30 天)
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 个评论
dpb
dpb 2023-4-6
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>

请先登录,再进行评论。

回答(1 个)

Peter Perkins
Peter Perkins 2023-4-6
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

类别

Help CenterFile Exchange 中查找有关 Data Type Conversion 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by