Como devo atualizar os dados de um lote no Matlab?

Suponha que eu queira atualizar um gráfico com novos dados. Qual método devo escolher?

  1. Defina a propriedade XDataSource como um nome, atualize a variável e chame refreshdata
  2. Apague o plot original e chame o comando de plot novamente.
  3. Use Set('Xdata',...')

    Resposta curta: use sempre Set('Xdata',...') .

    Exemplo de código:

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

    Resposta longa:

    Existem três medidas relevantes pelas quais se deve escolher o melhor método.

    1. Clareza de código – como é fácil para alguém ler seu código?
    2. Runtime – Quão rápido cada método realiza sua tarefa?
    3. Portabilidade de código – Com que rapidez você pode refatorar seu código?

    Agora, vamos analisar os methods possíveis.

    Método (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 emite imediatamente um aviso na linha y=sin(x.^3)

     The value assigned to variable `y` might be unused 

    Por que isso acontece? refreshdata usa eval e m-lint não pode saber que você usará y . Alguém que lê seu código também pode remover essa linha completamente. Isso aconteceu porque você quebrou o princípio de encapsulamento. refreshdata acessa variables ​​da área de trabalho do chamador. Outra maneira de dar uma olhada nisso, suponha que você passe a alça da plotagem para outra function. O leitor não tem idéia do porquê você escreveu y = sin(x.^3); e como isso será relacionado à atualização do enredo?

    Agora vamos discutir velocidade / tempo de execução. Ao dar uma olhada no código-fonte refreshdata , você notará dois loops for-loops, que passam por todas as variables ​​de handles de charts em seu espaço. Aqui está o primeiro:

     % 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 que você não tem um enredo, mas 100 enredo e você deseja atualizar apenas o primeiro. Isso será muito lento, porque para cada um dos lotes você tenta encontrar o que precisa! (Eu estou saindo como um exercício para o leitor descobrir o que é ecruoSataD e como ele é usado.)

    Mesmo se você der o enredo relevante como um argumento, você ainda terá o segundo loop, que executa o eval várias vezes. Não é exatamente eficiente. Eu mostrarei uma comparação de tempo no final.

    Conclusão: Difícil de entender, difícil de refatorar, tempo de execução lento


    Método (2) – Excluir e refazer o traçado

     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 

    Este método é bastante claro para o leitor. Você excluiu o enredo e desenhou um novo. No entanto, como veremos na comparação de tempo no final, esse é o método mais lento.

    Conclusão: Fácil de entender, fácil de refatorar, tempo de execução muito lento


    Método (3) – set (‘XData’, …, ‘YData’)

    O código é muito claro. Você deseja modificar duas propriedades do seu gráfico, XData e YData . E isso é exatamente o que você faz. Além disso, o código é executado muito rápido, como você pode ver na comparação abaixo.

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

    Desde o novo motor gráfico hg2 (R2014b e acima), você também pode usar a syntax da propriedade para especificar dados se preferir essa notação:

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

    Conclusão: Fácil de entender, fácil de refatorar, tempo de execução rápido


    Aqui está o código de comparação de tempo

     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 

    E os resultados:

    O tempo decorrido é de 0,075515 segundos.
    O tempo decorrido é de 0,179954 segundos.
    O tempo decorrido é de 0,002820 segundos.

    Você pode chamar a function drawnow e fazer algo assim:

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

    Suponha que eu queira atualizar um gráfico com novos dados. Qual método devo escolher?

    Se você tiver mais de um object de linha nos eixos especificados, então Método:

    1. Defina a propriedade XDataSource como um nome, atualize a variável e chame refreshdata

    irá gerar um erro no MATLAB R2012b. Um exemplo apropriado é fornecido na resposta de Andrey.

    Um bug foi enviado para o Mathworks.