35

プロットを新しいデータで更新したいとします。どの方法を選ぶべきですか?

  1. プロパティをある名前に設定しXDataSource、変数を更新して、refreshdata
  2. 元のを消去して、コマンドを再plot呼び出ししてください。plot
  3. 使用するSet('Xdata',...')
4

3 に答える 3

57

簡単な答え:常にを使用して 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. ランタイム-各メソッドがそのタスクを実行する速度はどれくらいですか?
  3. コードの移植性-コードをどのくらいの速さでリファクタリングできますか?

それでは、考えられる方法を分析しましょう。

Method(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通過する2つの醜い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、そしてそれがどのように使用されるかを理解するための演習として残しています。)

関連するプロットを引数として指定した場合でも、2番目のループがあります。これは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

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

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


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秒です。

于 2012-10-27T17:53:14.513 に答える
2

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

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

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

MATLAB R2012b でエラーが発生します。Andrey's answer に適切な例が示されています。

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

于 2012-10-29T06:32:12.007 に答える