Как мне обновить данные сюжета в Matlab?

32

Предположим, что я хочу обновить график новыми данными. Какой метод выбрать?

  • Задайте для свойства XDataSource какое-то имя, обновите переменную и вызовите refreshdata
  • Удалите оригинал plot и снова вызовите команду plot.
  • Используйте Set('Xdata',...')
Теги:
matlab-figure
matlab-guide
graph
plot

3 ответа

52
Лучший ответ

Короткий ответ: всегда используйте 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) - refreshdata​​strong >

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-loops, которые проходят через все графики, обрабатывая переменные в вашем пространстве. Вот первый:

% 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

Представьте, что у вас нет ни одного сюжета, а всего 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 секунд.

  • 2
    И вы можете добавить в метод (1), что refreshdata работает в R2012b
  • 0
    @ MattLab, спасибо за информацию. У меня не установлен 2012b. Можете ли вы привести пример или указать ссылку? Вы также можете добавить этот факт в качестве другого ответа на вопрос.
Показать ещё 3 комментария
3

Вы можете вызвать функцию drawnow и сделать что-то вроде этого:

h = plot(nan);

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

Предположим, что я хочу обновить график новыми данными. Какой метод выбрать?

Если у вас есть несколько объектов линии в заданных осях, тогда Method:

  • Установите для свойства XDataSource какое-то имя, обновите переменную и вызовите refreshdata

генерирует ошибку в MATLAB R2012b. Соответствующий пример приведен в ответе Андрея.

В Mathworks была отправлена ​​ошибка.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню