make patch white where there are NaNs

12 views (last 30 days)
Hi All,
I would like to use patch to make uncertainty bounds around timeseries data, but the data has NaNs. I can remove the NaNs from the patch datasets, but then I get nasty straight lines where it interpolates between the missing data. Since I am dealing with timeseries data the gaps in time with no data should remain. I thought of somehow making another white patch that goes only where there are NaNs but this would require dealing with every gap seperately, and finding their indices, which seems quite a pain given that there are many gaps. Any suggestons welcome!
Here's a simple example:
figure();
DT = datetime(2000,1,1):datetime(2000,12,31); DT=DT'; sizeDT = size(DT,1);
X_data = rand(sizeDT,1);
X_data(5:40)=NaN; X_data(100:120)=NaN; %make some NaN
idnans = isnan(X_data);
lb = X_data - (X_data.*0.3);
ub = X_data + (X_data.*0.3);
DTnn = DT; DTnn(idnans)=[]; lbnn = lb; lbnn(idnans)=[]; ubnn=ub; ubnn(idnans)=[];
patch([DTnn' fliplr(DTnn')],[lbnn' flipud(ubnn)'],'b','FaceAlpha',.2, 'EdgeColor','none'); hold on;
%modelled
plot(DT,X_data,'Color','b','LineStyle','-'); hold on;
legend('uncertainty','data');
Thanks!!
  2 Comments
dpb
dpb on 5 Mar 2025
figure();
DT = datetime(2000,1,1):datetime(2000,12,31); DT=DT'; sizeDT = size(DT,1);
X_data = rand(sizeDT,1);
X_data(5:40)=NaN; X_data(100:120)=NaN; %make some NaN
idnans = isnan(X_data);
lb = X_data - (X_data.*0.3);
ub = X_data + (X_data.*0.3);
DTnn = DT; DTnn(idnans)=[]; lbnn = lb; lbnn(idnans)=[]; ubnn=ub; ubnn(idnans)=[];
patch([DTnn' fliplr(DTnn')],[lbnn' flipud(ubnn)'],'b','FaceAlpha',.2, 'EdgeColor','none'); hold on;
%modelled
plot(DT,X_data,'Color','b','LineStyle','-'); hold on;
legend('uncertainty','data');
Name Size Bytes Class Attributes DTnn 309x1 2472 datetime
It's not clear what you want the end result to be??? With a white background a white patch is/will be unseen, so what's the point?
As for dealing with the missing data sections, patch can create multiple polygons in a single call, where each is specificed by the corner coordinates in X,Y arrays; each column in X and Y defines a separate area. But, you will indeed have to locate the ends of the missing sections. How much trouble that may be will probably depend upon the sampling scheme; if it is a uniformly sampled time history, then any gap other than the sample time is missing and easy to find. Turning the data into a timetable would probably make things easier with retime.
Catriona Fyffe
Catriona Fyffe on 5 Mar 2025
Dear dpb - thanks for getting back so quick, and I'm sorry I wasn't so clear. I meant that I wanted the patch where there were NaNs to not be shown somehow, but I wasn't sure of the best way. I think Voss has solved it though which is great.

Sign in to comment.

Accepted Answer

Voss
Voss on 5 Mar 2025
Edited: Voss on 5 Mar 2025
In this case, the patch's EdgeColor is 'none', so wherever the upper and lower patch bounds coincide, no edge is rendered and the patch does not appear at all in those regions. Therefore, rather than removing the elements of DTnn, lbnn, and ubnn where X_data is NaN, you can merely set those elements of lbnn and ubnn to the same value so that the upper and lower bounds of the patch coincide. [To get the patch to look right at the gap edges, I use fillmissing(_,'linear') to fill the NaNs in lbnn and ubnn with their own respective line segments and then take the mean of the two to get a single line segment for each gap.]
figure();
DT = (datetime(2000,1,1):datetime(2000,12,31)).';
X_data = rand(size(DT));
X_data([5:40 100:120])=NaN; %make some NaN
idnans = isnan(X_data);
lb = 0.7*X_data;
ub = 1.3*X_data;
DTnn = DT;
lbnn = lb;
ubnn = ub;
tmp = mean(fillmissing([lbnn ubnn],'linear'),2);
lbnn(idnans)=tmp(idnans);
ubnn(idnans)=tmp(idnans);
patch([DTnn; flipud(DTnn)],[lbnn; flipud(ubnn)],'b','FaceAlpha',0.2, 'EdgeColor','none');
hold on;
plot(DT,X_data,'Color','b','LineStyle','-');
legend('uncertainty','data');
% zoomed-in copy to show a gap
copyobj([gca() gca().Legend],figure())
xlim(DT([80 140]))
  2 Comments
Catriona Fyffe
Catriona Fyffe on 5 Mar 2025
This is exactly what I was looking for! I would not have thought of using that trick of setting the Edge Color to 'none. Thanks!

Sign in to comment.

More Answers (0)

Products


Release

R2022b

Community Treasure Hunt

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

Start Hunting!