我应该如何更新 Matlab 中的绘图数据?
Posted
技术标签:
【中文标题】我应该如何更新 Matlab 中的绘图数据?【英文标题】:How should I update the data of a plot in Matlab? 【发布时间】:2012-10-17 15:32:23 【问题描述】:假设我想用新数据更新绘图。我应该选择什么方法?
-
将
XDataSource
属性设置为某个名称,更新变量,然后调用refreshdata
抹掉原来的plot
,再次调用plot
命令。
使用Set('Xdata',...')
【问题讨论】:
相关:Real time plot in matlab 【参考方案1】:简短的回答:总是使用 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) - 刷新数据
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(objfieldsk2),'ecruoSataD',10)
objs = objs:,obj, objfieldsk2;
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) - set('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 秒。
【讨论】:
并且您可以将refreshdata
在 R2012b 中损坏的方法 (1) 添加到
@MattLab,感谢您提供的信息。我没有安装2012b。你能举个例子,或指出一些参考吗?您还可以将此事实添加为问题的另一个答案。
好点。我修正了“首选”代码中的一个错字——你叫set(h,'XDataSource',x)
,我认为是复制粘贴错字。第一个代码 sn-p 没有这些。否则,我明白你的意思。虽然另一方面,如果您有 100 个图要刷新,调用 refreshdata
是一行,而在重新计算输入数据后调用 set(h, ...)
100 次可能有点乏味。
另外:当你想在回调中编辑数据时,使用set('XData')
比refreshdata
更容易。您唯一需要搜索(或使用persistent
缓存)是图形句柄。我在尝试自动链接内容时遇到了麻烦,切换到 XData 后非常流畅。
h.XData = x; h.YData = y;
在我的机器上实际上比同等的 set(h,'XData',x,'YData',y);
快 33%。我已经在您的脚本中进行了测试,设置 i=1:1000 的总时间为 0.058861 秒与 0.088543 秒。【参考方案2】:
假设我想用新数据更新绘图。我应该选择什么方法?
如果您在给定的轴上有多个线对象,则方法:
将 XDataSource 属性设置为某个名称,更新变量,然后调用
refreshdata
将在 MATLAB R2012b 中生成错误。 Andrey 的回答中提供了一个适当的例子。
一个错误已提交给 Mathworks。
【讨论】:
【参考方案3】:您可以调用函数drawnow
并执行类似的操作:
h = plot(nan);
for i = 1:n
y = ...
set(h,'YData',y);
drawnow %update the graph
end
【讨论】:
以上是关于我应该如何更新 Matlab 中的绘图数据?的主要内容,如果未能解决你的问题,请参考以下文章
通过将数字分组到一个范围内在 matlab / octave 中绘图
MATLAB | 绘图复刻 | 分层聚类分析图:树状图+热图