如何在Matlab中更新plot的数据?

时间:2022-03-30 15:10:16

Suppose that I want to update a plot with a new data. What method should I choose?

假设我想用一个新数据更新一个图。我应该选择什么方法?

  1. Set the XDataSource property to some name, update the variable, and call refreshdata
  2. 将XDataSource属性设置为某个名称,更新变量,并调用refreshdata。
  3. Erase the original plot, and call plot command again.
  4. 删除原始的情节,再调用plot命令。
  5. Use Set('Xdata',...')
  6. 使用设置(Xdata,……)

3 个解决方案

#1


53  

Short answer : always use Set('Xdata',...').

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

Example code:

示例代码:

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

Long answer:

长一点的回答:

There are three relevant measures by which one should choose the best method.

有三个相关的措施,一个人应该选择最好的方法。

  1. Code clarity - How easy it is for someone to read your code?
  2. 代码清晰——一个人阅读你的代码有多容易?
  3. Runtime - How quick each method performs its task?
  4. 运行时——每个方法执行任务的速度有多快?
  5. Code portability - How fast can you re-factor your code?
  6. 代码可移植性——你能多快地重构你的代码?

Now, let's analyze the possible methods.

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

Method(1) - refreshdata

方法(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

M-lint immediately issues a warning in the line y=sin(x.^3)

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

The value assigned to variable `y` might be unused

Why does it happen? refreshdata uses eval and m-lint cannot know that you will use y. Someone reading your code, might as well remove this line completely. This happened because you broke the encapsulation principle. refreshdata accesses variables from the caller workspace. Another way to take a look at this, suppose that you pass the handle of the plot to another function. The reader has no clue to why on earth you wrote y = sin(x.^3);, and how is it going to be related to the update of the plot.

为什么会发生?refreshdata使用eval和m-lint不知道您将使用y。有人阅读您的代码,不妨完全删除这一行。这是因为您打破了封装原则。refreshdata从调用者工作区访问变量。另一种方法是,假设将绘图的句柄传递给另一个函数。读者还不知道究竟为什么你写y =罪(x ^ 3);,它是如何与情节的更新。

Now let's discuss speed/runtime. By taking a look at refreshdata source code, you will notice two ugly for-loops, that go through all of the graphics handles variables in your space. Here is the first:

现在,让我们讨论一下速度/运行时。通过查看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

Imagine that you have not one plot, but 100 plot and you want to update only the first. This will be very slow, because for each of the plots, you attempt to find the one you need! (I am leaving as an exercise for the reader to figure out what is ecruoSataD, and how it is used.)

想象一下,你没有一个情节,但是有100个情节,你想要只更新第一个情节。这将是非常缓慢的,因为对于每一个情节,你试图找到你需要的!(我将作为一个练习留给读者去理解什么是ecruoSataD,以及它是如何使用的。)

Even if you give the relevant plot as an argument, you still have the second loop, that runs eval several times. Not exactly efficient. I will show a time comparison in the end.

即使你把相关的情节作为一个参数,你仍然有第二个循环,它运行eval几次。不完全有效。我将在最后给出一个时间比较。

Conclusion : Hard to understand, hard to refactor, slow runtime

结论:难以理解,难以重构,运行缓慢。


Method (2) - Delete and re-plot

方法(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

This method is quite clear for the reader. You deleted the plot, and drew a new one. However, as we will see from the time comparison in the end, that is the slowest method.

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

Conclusion : Easy to understand, easy to refactor, very slow runtime

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


Method(3) - set('XData',...,'YData')

方法(3)——集(XData,…,“YData”)

The code is really clear. You want to modify a two properties of your plot, XData and YData. And that is exactly what you do. Also, the code runs really fast, as you can see from the comparison below.

代码非常清晰。您需要修改plot、XData和YData的两个属性。这就是你所做的。而且,代码运行得非常快,您可以从下面的比较中看到。

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

Since the new graphics engine hg2 (R2014b and up), you can also use property syntax for specifying data if you prefer that notation:

由于新的图形引擎hg2 (R2014b和up),您还可以使用属性语法来指定数据,如果您喜欢这样的符号:

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

Conclusion : Easy to understand, easy to refactor, fast runtime

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


Here is the time comparison code

这里是时间比较代码。

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

And the results:

结果:

Elapsed time is 0.075515 seconds.
Elapsed time is 0.179954 seconds.
Elapsed time is 0.002820 seconds.

运行时间是0.075515秒。运行时间为0.179954秒。运行时间是0.002820秒。

#2


3  

You can call the function drawnow and do something like that :

你可以调用函数drawnow,然后这样做:

h = plot(nan);

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

#3


2  

Suppose that I want to update a plot with a new data. What method should I choose?

假设我想用一个新数据更新一个图。我应该选择什么方法?

If you have more than one line object in the given axes then Method:

如果在给定的坐标轴中有多个行对象,那么方法:

  1. Set the XDataSource property to some name, update the variable, and call refreshdata
  2. 将XDataSource属性设置为某个名称,更新变量,并调用refreshdata。

will generate an error in MATLAB R2012b. An appropriate example is provided in Andrey's answer.

将在MATLAB R2012b中产生错误。在Andrey的回答中给出了一个适当的例子。

A bug has been submitted to the Mathworks.

已经向Mathworks提交了一个bug。

#1


53  

Short answer : always use Set('Xdata',...').

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

Example code:

示例代码:

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

Long answer:

长一点的回答:

There are three relevant measures by which one should choose the best method.

有三个相关的措施,一个人应该选择最好的方法。

  1. Code clarity - How easy it is for someone to read your code?
  2. 代码清晰——一个人阅读你的代码有多容易?
  3. Runtime - How quick each method performs its task?
  4. 运行时——每个方法执行任务的速度有多快?
  5. Code portability - How fast can you re-factor your code?
  6. 代码可移植性——你能多快地重构你的代码?

Now, let's analyze the possible methods.

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

Method(1) - refreshdata

方法(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

M-lint immediately issues a warning in the line y=sin(x.^3)

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

The value assigned to variable `y` might be unused

Why does it happen? refreshdata uses eval and m-lint cannot know that you will use y. Someone reading your code, might as well remove this line completely. This happened because you broke the encapsulation principle. refreshdata accesses variables from the caller workspace. Another way to take a look at this, suppose that you pass the handle of the plot to another function. The reader has no clue to why on earth you wrote y = sin(x.^3);, and how is it going to be related to the update of the plot.

为什么会发生?refreshdata使用eval和m-lint不知道您将使用y。有人阅读您的代码,不妨完全删除这一行。这是因为您打破了封装原则。refreshdata从调用者工作区访问变量。另一种方法是,假设将绘图的句柄传递给另一个函数。读者还不知道究竟为什么你写y =罪(x ^ 3);,它是如何与情节的更新。

Now let's discuss speed/runtime. By taking a look at refreshdata source code, you will notice two ugly for-loops, that go through all of the graphics handles variables in your space. Here is the first:

现在,让我们讨论一下速度/运行时。通过查看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

Imagine that you have not one plot, but 100 plot and you want to update only the first. This will be very slow, because for each of the plots, you attempt to find the one you need! (I am leaving as an exercise for the reader to figure out what is ecruoSataD, and how it is used.)

想象一下,你没有一个情节,但是有100个情节,你想要只更新第一个情节。这将是非常缓慢的,因为对于每一个情节,你试图找到你需要的!(我将作为一个练习留给读者去理解什么是ecruoSataD,以及它是如何使用的。)

Even if you give the relevant plot as an argument, you still have the second loop, that runs eval several times. Not exactly efficient. I will show a time comparison in the end.

即使你把相关的情节作为一个参数,你仍然有第二个循环,它运行eval几次。不完全有效。我将在最后给出一个时间比较。

Conclusion : Hard to understand, hard to refactor, slow runtime

结论:难以理解,难以重构,运行缓慢。


Method (2) - Delete and re-plot

方法(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

This method is quite clear for the reader. You deleted the plot, and drew a new one. However, as we will see from the time comparison in the end, that is the slowest method.

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

Conclusion : Easy to understand, easy to refactor, very slow runtime

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


Method(3) - set('XData',...,'YData')

方法(3)——集(XData,…,“YData”)

The code is really clear. You want to modify a two properties of your plot, XData and YData. And that is exactly what you do. Also, the code runs really fast, as you can see from the comparison below.

代码非常清晰。您需要修改plot、XData和YData的两个属性。这就是你所做的。而且,代码运行得非常快,您可以从下面的比较中看到。

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

Since the new graphics engine hg2 (R2014b and up), you can also use property syntax for specifying data if you prefer that notation:

由于新的图形引擎hg2 (R2014b和up),您还可以使用属性语法来指定数据,如果您喜欢这样的符号:

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

Conclusion : Easy to understand, easy to refactor, fast runtime

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


Here is the time comparison code

这里是时间比较代码。

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

And the results:

结果:

Elapsed time is 0.075515 seconds.
Elapsed time is 0.179954 seconds.
Elapsed time is 0.002820 seconds.

运行时间是0.075515秒。运行时间为0.179954秒。运行时间是0.002820秒。

#2


3  

You can call the function drawnow and do something like that :

你可以调用函数drawnow,然后这样做:

h = plot(nan);

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

#3


2  

Suppose that I want to update a plot with a new data. What method should I choose?

假设我想用一个新数据更新一个图。我应该选择什么方法?

If you have more than one line object in the given axes then Method:

如果在给定的坐标轴中有多个行对象,那么方法:

  1. Set the XDataSource property to some name, update the variable, and call refreshdata
  2. 将XDataSource属性设置为某个名称,更新变量,并调用refreshdata。

will generate an error in MATLAB R2012b. An appropriate example is provided in Andrey's answer.

将在MATLAB R2012b中产生错误。在Andrey的回答中给出了一个适当的例子。

A bug has been submitted to the Mathworks.

已经向Mathworks提交了一个bug。