假设我想用新数据更新图表。我应该选择什么方法?
XDataSource
属性设置为某个名称,更新变量,然后调用refreshdata
plot
,然后再次调用plot
命令。Set('Xdata',...')
答案 0 :(得分:54)
简答:始终使用 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
答案很长:
有三种相关措施可以选择最佳方法。
现在,让我们分析可能的方法。
方法(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会立即在行y=sin(x.^3)
The value assigned to variable `y` might be unused
为什么会这样? 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
想象一下,你没有一个情节,而是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
这种方法对读者来说非常清楚。你删除了情节,并画了一个新的情节。但是,正如我们将从时间比较中看到的那样,这是最慢的方法。
结论:易于理解,易于重构,运行速度非常慢
方法(3) - 设置('XData',...,'YData')
代码非常清楚。您想要修改地图的两个属性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
自新图形引擎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秒。
答案 1 :(得分:3)
您可以调用函数drawnow
并执行类似的操作:
h = plot(nan);
for i = 1:n
y = ...
set(h,'YData',y);
drawnow %update the graph
end
答案 2 :(得分:2)
假设我想用新数据更新图表。我应该选择什么方法?
如果给定轴中有多个线对象,则方法:
- 将XDataSource属性设置为某个名称,更新变量,然后调用
醇>refreshdata
将在MATLAB R2012b中生成错误。安德烈的答案提供了一个恰当的例子。
已向Mathworks提交错误。