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

And*_*ein 33 matlab plot graph matlab-figure matlab-guide

假设我想用新数据更新绘图.我应该选择什么方法?

  1. XDataSource属性设置为某个名称,更新变量并调用refreshdata
  2. 再次删除原始plot和呼叫plot命令.
  3. 使用 Set('Xdata',...')

And*_*ein 55

简答:总是用 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
Run Code Online (Sandbox Code Playgroud)

答案很长:

有三种相关措施可以选择最佳方法.

  1. 代码清晰度 - 人们阅读代码有多容易?
  2. 运行时 - 每个方法执行任务的速度有多快?
  3. 代码可移植性 - 您可以多快地重新编写代码?

现在,让我们分析可能的方法.

方法(1) - refreshdata

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
Run Code Online (Sandbox Code Playgroud)

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

The value assigned to variable `y` might be unused
Run Code Online (Sandbox Code Playgroud)

为什么会这样? refreshdata使用eval,m-lint不知道你会使用y.阅读代码的人也可以完全删除这一行.发生这种情况是因为你打破了封装原则.refreshdata从调用者工作区访问变量.另一种看待这个的方法,假设您将绘图的句柄传递给另一个函数.读者不清楚为什么你写的地球y = sin(x.^3);,以及它如何与剧情的更新有关.

现在让我们讨论速度/运行时间.通过查看refreshdata源代码,您会注意到两个丑陋的for循环,它们遍历您空间中的所有图形处理变量.这是第一个:

% 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
Run Code Online (Sandbox Code Playgroud)

想象一下,你没有一个情节,而是100个情节,你想只更新第一个情节.这将是非常缓慢的,因为对于每个图,你试图找到你需要的那个!(我将离开作为练习让读者弄清楚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
Run Code Online (Sandbox Code Playgroud)

这种方法对读者来说非常清楚.你删除了情节,并画了一个新的情节.但是,正如我们将从时间比较中看到的那样,这是最慢的方法.

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


方法(3) - 设置('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
Run Code Online (Sandbox Code Playgroud)

从新的图形引擎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
Run Code Online (Sandbox Code Playgroud)

结论:易于理解,易于重构,运行时间快


这是时间比较代码

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
Run Code Online (Sandbox Code Playgroud)

结果如下:

经过时间为0.075515秒.
经过的时间是0.179954秒.
经过时间为0.002820秒.

  • **和**你可以在方法(1)中添加`refreshdata`在R2012b中被破坏 (2认同)