web-dev-qa-db-ja.com

Matlabのプロットのデータを更新するにはどうすればよいですか?

新しいデータでプロットを更新するとします。どの方法を選択すればよいですか?

  1. XDataSourceプロパティに何らかの名前を設定し、変数を更新して、refreshdataを呼び出します
  2. 元のplotを消去し、plotコマンドを再度呼び出します。
  3. Set('Xdata',...')を使用します
33

短い答え:常に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
_

長答:

最適な方法を選択するための3つの関連する手段があります。

  1. コードの明瞭さ-誰かがあなたのコードを読むのはどれくらい簡単ですか?
  2. Runtime-各メソッドがタスクを実行する速さ
  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
_

なぜ起こるのですか? refreshdataevalを使用し、_m-lint_はyを使用することを認識できません。コードを読んでいる人は、この行を完全に削除することもできます。これは、カプセル化の原則を破ったために発生しました。 refreshdataは、呼び出し元のワークスペースから変数にアクセスします。これを見る別の方法として、プロットのハンドルを別の関数に渡すと仮定します。読者は、いったいなぜあなたがy = sin(x.^3);を書いたのか、そしてそれがプロットの更新とどのように関係するのかについての手掛かりを持っていません。

次に、速度/実行時間について説明します。 refreshdataソースコードを見ると、グラフィックハンドル変数のallを通過する2つのforい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
_

1つのプロットではなく、100のプロットがあり、最初のプロットのみを更新したいとします。これは非常に遅くなります。なぜなら、プロットごとに、必要なプロットを見つけようとするからです! (読者がecruoSataDとは何か、どのように使用されるかを理解するための演習として残しておきます。)

関連するプロットを引数として指定した場合でも、evalを数回実行する2番目のループがあります。正確には効率的ではありません。最後に時間比較を示します。

結論:理解するのが難しく、リファクタリングするのが難しく、ランタイムが遅い


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

この方法は、読者にとって非常に明確です。プロットを削除し、新しいプロットを描きました。ただし、最後の時間比較からわかるように、これが最も遅い方法です。

結論:理解しやすく、リファクタリングしやすく、実行時間が非常に遅い


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

コードは本当に明確です。プロットの2つのプロパティ、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秒です。

54

関数drawnowを呼び出して、そのようなことを行うことができます。

h = plot(nan);

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

新しいデータでプロットを更新するとします。どの方法を選択すればよいですか?

指定された軸に複数のラインオブジェクトがある場合、メソッド:

  1. XDataSourceプロパティに名前を設定し、変数を更新して、refreshdataを呼び出します

mATLAB R2012bでエラーを生成します。適切な例は、Andreyの回答に記載されています。

バグがMathworksに提出されました。

2
MattLab