¿Cómo debo actualizar los datos de una plot en Matlab?

Supongamos que quiero actualizar un gráfico con nuevos datos. ¿Qué método debo elegir?

  1. Establezca la propiedad XDataSource a algún nombre, actualice la variable y llame a refreshdata
  2. Borre el plot original y llame al comando plot nuevamente.
  3. Use Set('Xdata',...')

Respuesta corta: use siempre Set('Xdata',...') .

Código de ejemplo:

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

Respuesta larga:

Hay tres medidas relevantes por las cuales uno debe elegir el mejor método.

  1. Claridad del código : ¿Qué tan fácil es para alguien leer su código?
  2. Tiempo de ejecución : ¿Cuán rápido realiza cada método su tarea?
  3. Portabilidad del código : ¿con qué rapidez puede volver a factorizar su código?

Ahora, analicemos los métodos posibles.

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 inmediatamente emite una advertencia en la línea y=sin(x.^3)

 The value assigned to variable `y` might be unused 

¿Por que sucede? refreshdata usa eval y m-lint no puede saber que usará y . Alguien que lea tu código, bien podría eliminar esta línea por completo. Esto sucedió porque rompiste el principio de encapsulación. refreshdata accede a las variables del espacio de trabajo de la persona que llama. Otra forma de ver esto, suponga que pasa el control de la ttwig a otra función. El lector no tiene idea de por qué en la tierra escribiste y = sin(x.^3); y cómo va a estar relacionado con la actualización de la ttwig.

Ahora veamos la velocidad / tiempo de ejecución. Si echas un vistazo al código fuente de refreshdata , verás dos feos bucles for, que pasan por todas las variables de manejo de gráficos en tu espacio. Aquí está el primero:

 % 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 

Imagina que no tienes una ttwig, sino una ttwig de 100 y quieres actualizar solo la primera. Esto será muy lento, porque para cada una de las plots, ¡intentas encontrar la que necesitas! (Me voy como ejercicio para que el lector ecruoSataD qué es ecruoSataD y cómo se usa).

Incluso si das el argumento relevante como argumento, todavía tienes el segundo ciclo, que ejecuta eval varias veces. No es exactamente eficiente. Mostraré una comparación de tiempo al final.

Conclusión: difícil de entender, difícil de refactorizar, tiempo de ejecución lento


Método (2) – Eliminar y volver a trazar

 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 es bastante claro para el lector. Eliminaste la ttwig y dibujaste una nueva. Sin embargo, como veremos en la comparación de tiempo al final, ese es el método más lento.

Conclusión: fácil de entender, fácil de refactorizar, tiempo de ejecución muy lento


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

El código es muy claro. Desea modificar dos propiedades de su trazado, XData e YData . Y eso es exactamente lo que haces. Además, el código se ejecuta muy rápido, como puede ver en la comparación a continuación.

 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 el nuevo motor de gráficos hg2 (R2014b y superior), también puede usar la syntax de propiedades para especificar datos si prefiere esa notación:

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

Conclusión: fácil de entender, fácil de refactorizar, rápido tiempo de ejecución


Aquí está el código de comparación de tiempo

 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 

Y los resultados:

El tiempo transcurrido es 0.075515 segundos.
El tiempo transcurrido es 0.179954 segundos.
El tiempo transcurrido es 0.002820 segundos.

Puede llamar a la función drawnow y hacer algo como eso:

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

Supongamos que quiero actualizar un gráfico con nuevos datos. ¿Qué método debo elegir?

Si tiene más de un objeto de línea en los ejes dados, entonces Método:

  1. Establezca la propiedad XDataSource a algún nombre, actualice la variable y llame a refreshdata

generará un error en MATLAB R2012b. Un ejemplo apropiado se proporciona en la respuesta de Andrey.

Se ha enviado un error al Mathworks.