我应该如何更新Matlab中的图的数据?

假设我想更新一个新的数据的情节。 我应该select什么方法?

  1. XDataSource属性设置为某个名称,更新该variables并调用refreshdata
  2. 擦除原始plot ,然后再次调用plot命令。
  3. 使用Set('Xdata',...')

简短的回答:总是使用 Set('Xdata',...')

示例代码:

 function PlotUpdate() x = 0:.1:8; y = sin(x); h = plot(x,y); y = sin(x.^3); set(h,'XData',x,'YData',y); end 

很长的回答:

有三个相关的措施,应该select最好的方法。

  1. 代码清晰度 – 有人阅读你的代码有多容易?
  2. 运行时间 – 每种方法执行任务的速度有多快?
  3. 代码可移植性 – 您可以将代码重新分配多快?

现在,我们来分析一下可能的方法。

方法(1) – 刷新数据

 function PlotUpdate() x = 0:.1:8; y = sin(x); h = plot(x,y); set(h,'YDataSource','y') set(h,'XDataSource','x') y = sin(x.^3); refreshdata(h,'caller'); end 

M-lint立即在y=sin(x.^3)行发出警告,

 The value assigned to variable `y` might be unused 

为什么会发生? refreshdata使用evalm-lint无法知道您将使用y 。 有人读你的代码,不妨完全删除这一行。 这是因为你打破了封装原则。 refreshdata从调用者工作区访问variables。 另一种方法来看看这个,假设你将图的句柄传递给另一个函数。 读者不知道你为什么写y = sin(x.^3); ,以及如何与情节的更新有关。

现在我们来讨论速度/运行时间。 通过查看refreshdata源代码,您将注意到两个丑陋的for循环,它们遍历您空间中的所有graphics句柄variables。 这是第一个:

 % gather up all the objects to refresh objs = {}; for k = 1:length(h) obj = h(k); objfields = fields(obj); for k2 = 1:length(objfields) % search for properties ending in DataSource if strncmpi(fliplr(objfields{k2}),'ecruoSataD',10) objs = {objs{:},obj, objfields{k2}}; end end end 

想象一下,你没有一个情节,而是100个情节,你只想更新第一个情节。 这将是非常缓慢的,因为对每个地块,你试图find你需要的一个! (我正在离开,作为练习让读者找出什么是ecruoSataD ,以及它是如何使用的。)

即使你把相关的情节作为一个参数,你仍然有第二个循环,多次运行eval 。 不完全有效。 最后我会展示一下时间比较。

结论:很难理解,很难重构,运行时间较慢


方法(2) – 删除并重新绘制

 function PlotUpdate() x = 0:.1:8; y = sin(x); h = plot(x,y); set(h,'YDataSource','y') set(h,'XDataSource','x') y = sin(x.^3); delete(h); h = plot(x,y); end 

这个方法对读者来说很清楚。 你删除了阴谋,并画了一个新的。 但是,从最后的时间比较来看,这是最慢的方法。

结论:易于理解,易于重构,运行时间非常慢


方法(3) – set('XData',…,'YData')

代码非常清晰。 你想修改你的图的两个属性, XDataYData 。 而这正是你所做的。 而且,代码的运行速度非常快,您可以从下面的比较中看到。

 function PlotUpdate() x = 0:.1:8; y = sin(x); h = plot(x,y); y = sin(x.^3); set(h,'XData',x,'YData',y); end 

由于新的graphics引擎hg2(R2014b及更高版本),如果您喜欢这种表示法,您还可以使用属性语法指定数据:

 function PlotUpdate() x = 0:.1:8; y = sin(x); h = plot(x,y); y = sin(x.^3); h.XData = x; h.YData = y; end 

结论:易于理解,易于重构,运行速度快


这是时间比较代码

 function PlotUpdateTimeCompare() x = 0:.1:8; y = sin(x); h = plot(x,y); set(h,'YDataSource','y') set(h,'XDataSource','x') y = sin(x.^3); tic for i=1:100 refreshdata(h,'caller'); end toc tic for i=1:100 delete(h); h = plot(x,y); end toc tic for i=1:100 set(h,'XData',x,'YData',y); end toc end 

结果是:

已用时间为0.075515秒。
已用时间为0.179954秒。
经过的时间是0.002820秒。

你可以调用函数drawnow并做这样的事情:

 h = plot(nan); for i = 1:n y = ... set(h,'YData',y); drawnow %update the graph end 

假设我想更新一个新的数据的情节。 我应该select什么方法?

如果在给定坐标轴中有多个线对象,则方法:

  1. 将XDataSource属性设置为某个名称,更新该variables并调用refreshdata

会在MATLAB R2012b中产生一个错误。 安德烈的答案中提供了一个适当的例子。

一个错误已经提交给Mathworks。