Reputation: 195
Consider the following plot:
My data points are too dense, and I would like to hide or delete some of them points to make the chart clearer. How can I do this without without recomputing the data and re-plotting the figure (which is time-consuming)?
Upvotes: 1
Views: 10225
Reputation: 195
The simplest way:
In this way, the line continuity is retained and no coding is needed.
Upvotes: 3
Reputation: 10450
The most GUI way I can think of is selecting the point using the 'Data Cursor' tool to see what are its' values and then replace the XData and YData property of this point to NaN, at the 'More Properties' button.
Alternatively, you can alter the callback function of the 'Data Cursor' to do this for you (you can see here another example).
Check if the data points in your plot are a 'Scatter' graphic object, to do that type
get(gca,'children')
in the command window while the figure is chosen, and see if the first line of output is:
Scatter with properties:
if so, use option 1 below. If not, plot the data points and the lines as different objects, or use option 2 below.
After you create the figure, right click on one of the tooltips in the figure and choose Edit Text Update Function.
In the editor that opens add the following lines at the end:
event_obj.Target.XData(event_obj.Target.XData==pos(1)) = nan;
event_obj.Target.YData(event_obj.Target.YData==pos(2)) = nan;
Give the function some meaningful name, and save it as a new .m file.
Here is a simple example of what you should get:
function output_txt = DeletePoint(obj,event_obj) % Give it some meaningful name
% Display the position of the data cursor
% obj Currently not used (empty)
% event_obj Handle to event object
% output_txt Data cursor text string (string or cell array of strings).
pos = get(event_obj,'Position');
output_txt = {['X: ',num2str(pos(1),4)],...
['Y: ',num2str(pos(2),4)]};
% If there is a Z-coordinate in the position, display it as well
if length(pos) > 2
output_txt{end+1} = ['Z: ',num2str(pos(3),4)];
end
% The lines you add:
event_obj.Target.XData(event_obj.Target.XData==pos(1)) = nan;
event_obj.Target.YData(event_obj.Target.YData==pos(2)) = nan;
Now, right click again on one of the tooltips in the figure and choose Select Text Update Function. In the browser that opens choose the function you just saved (here, it's DeletePoint.m
).
Now, every click on a point using the 'Data Cursor' tool will delete it. However, keep in mind that the only way to restore the points is to newly create the figure, as the data is deleted from the figure (but not from the variables in the workspace that hold it).
In the editor that opens add the following lines at the end:
% The lines you add:
props = {'Color',...
'LineStyle',...
'LineWidth',...
'Marker',...
'MarkerSize',...
'MarkerEdgeColor',...
'MarkerFaceColor'};
line_props = get(event_obj.Target,props);
newX = event_obj.Target.XData;
newY = event_obj.Target.YData;
newX(newX==pos(1)) = [];
newY(newY==pos(2)) = [];
new_line = line(newX,newY);
set(new_line,props,line_props);
delete(event_obj.Target)
warning('off') % after you finish removing points, type warning('on') in the command window
All the rest is as in option 1. The difference here is that the latter function draws all the line again with the same properties, but without the point you selected. Normally, each time you delete a point the Data cursor automatically moves to the next point (and this is why we can't simply delete the points, it will initiate a loop that deletes the whole line). Here we delete the whole line, so Matlab issues a warning on every deletion:
Warning: Error while executing listener callback for MarkedClean event. Source has been deleted
To avoid that I added warning('off')
and the end of the function, but you should set them on again as soon as you finish with the Data cursor tool.
Upvotes: 1
Reputation: 24179
When plotting unconnected points, you can replace either the XData
or YData
(or both) of the points you don't want by NaN
. For charts with lines, this doesn't work (it creates discontinuities), and the appropriate points must be removed from the data vectors. I'll demonstrate how this is done in the example below:
For the purposes of demonstration, I shall assume that you're working with a .fig
file, and have no handles to the plots/lines.
Let this be the code used to plot a figure:
x = [0:0.05:0.9, 1:0.01:1.09, 1.1:0.1:pi/2];
figure(); plot(x,sin(x),'-+',x,sin(x-0.02),'-^',x,sin(x-0.04),'-s'); grid minor;
Then, assuming you loaded the figure and it is the current figure (gcf
), you can do:
function q45177572
%% Find handles:
hL = findobj(gcf,'Type','Line');
%% Choose which indices to remove, and remove...
for ind1 = 1:numel(hL)
% (Option 1) Keeping every other datapoint:
ind2rem = 1:2:numel(hL(ind1).XData);
% (Option 2) Removing points in a certain interval:
ind2rem = hL(ind1).XData > 1 & hL(ind1).XData < 1.05;
% (Option 3) Manual (watch out for indices out of bounds!)
ind2rem = [1 3 20:23 30];
% (Option 4) ...
% Finally, delete the points:
hL(ind1).XData(ind2rem) = [];
hL(ind1).YData(ind2rem) = [];
end
You can use whichever logic you want to compute ind2rem
, or even specify it manually.
The above was tested on R2017a.
Upvotes: 2