Plot multiple data sets fast - fastest/latest/efficient method up to R2023a

10 次查看(过去 30 天)
I want to plot >500 data sets with (1..N) points (N of each sets might be different) in a single graph - a axes allocated by calling nexttile() on a tiledlayout graphics object. Each set shall have its own color, displayname, etc. Here is my current snippet:
% plot N data series (xData, yData(i))
for idxY=1:numCells
line(obj.pltAxis, xData, yData(:, idxY),...
"DisplayName", yNames(idxY),...
"Marker", ".",...
"MarkerSize", 8,...
"LineStyle", "none",...
"Color", clrMap(idxY,:));
end
(I replaced plot with line but this yielded only a small improvement).
The profiler shows me that makeNumeric and configureAxes - both called by line() - accumulate the most time because the line() is called N times. Resetting the axes (limits) and converting X to numeric (although I provide doubles) is unneccessary, and it should be possible to avoid calling makeNumeric and configureAxes every loop iteration, right?
What is the best practice to achieve in < 1 sec (all features up to R2023a allowed)? I found the following (unsuitable/non-working) approaches on MATLAB Q&A:
  1. Concatenate the data, plot all points once -> not applicable, only useful for people who draw custom grids, or geographic features
  2. drawnow limitrate and drawnow -> increases loading time because. Why? Because MATLAB on "auto" decides to work through all data first and render only the final result. "limitrate" forces additional render update every 20 frames.
  3. plot(..., "EraseMode", "none") -> has been deprecated since R2014b, and might have not helped as it used to animate lines.
Is is possible and viable to preallocate all lines first, and then call drawnow expose?
% pseudo-code section %
ALLOC arrLines[N]
FOR i=1:N
arrLines(i).Parent = AXIS;
arrLines(i).XData = xData;
arrLines(i).YData = yData;
% ... color, display name, marker, marker size ...
END
plot(AXIS, arrLines)
  1 个评论
Mann Baidi
Mann Baidi 2023-8-16
Hey Florian,
I understand that you are facing time issues in plotting multiple lines in a single graph. I suggest you to avoid the loop you used for plotting the graph. Try using:
plot(xData,yData);

请先登录,再进行评论。

回答(2 个)

Siraj
Siraj 2023-8-23
Hii! @Florian Berzsenyi Hii! It is my understanding that you want to plot each column of “yData” against “xData”. I believe that “xData” is a vector and remains same for all the corresponding plots of columns of “yData”. As you suggested that the profiler shows that “makeNumeric” and “configureAxes both called by “line()” accumulates most time because “line()” is called N times.
We can use the “plotmatrix” function that creates a subplot for each column of “yData” and it return the axes and line objects which can be used to further modify the name, color, and other properties of the plot.
This way we avoid calling the “line()” function N time.
Attaching an example below.
xData = [1,2,3,4]'; %xData
yData = randi([0, 14], 4,3); %yData Matrix, each column corresponds to a line that is to be plotted.
yNames = ["A", "B", "C"]; %Corresponding display names of each set.
clrMap = ["red", "green", "blue"]; %Corresponding colors of each set.
[S,AX,BigAx,H,HAx] = plotmatrix(xData,yData, '-'); %plotting the entire dataset at once.
numCells = size(yData,2);
%Modying the properties of each plot to get the desired results.
for i=1:numCells
S(i).Color = clrMap(i);
S(i).DisplayName = yNames(i);
legend(AX(i), yNames(i));
end
Please refer to the documentation for more details on the “plotmatrix” function.
Hope this helps.
  3 个评论
Siraj
Siraj 2023-8-23
编辑:Siraj 2023-8-23
@Florian Berzsenyi So do you want all the lines to show up in a single axes.
Then we can direclty use the plot function.
xData = [1,2,3,4]'; %xData
yData = randi([0, 14], 4,3); %yData Matrix, each column corresponds to a line that is to be plotted.
yNames = ["A", "B", "C"]; %Corresponding display names of each set.
plot(xData,yData)
legend(yNames)
Hope this helps.

请先登录,再进行评论。


Bruno Luong
Bruno Luong 2023-8-23
编辑:Bruno Luong 2023-8-23
@Florian Berzsenyi Is is possible and viable to preallocate all lines first, and then call drawnow expose?
Yes.
Note the I permute yData for more efficiency in various plot commands.
m = 1000;
n = 100;
yData = rand(m, n);
ax = gca;
yNames = string(1:n);
xData = 1:m;
clrMap = rand(m,3);
tic
for idxY=1:n
line(ax, xData, yData(:, idxY),...
"DisplayName", yNames(idxY),...
"Marker", ".",...
"MarkerSize", 8,...
"LineStyle", "none",...
"Color", clrMap(idxY,:));
end
toc
Elapsed time is 0.066412 seconds.
cla(ax);
tic
h = plot(ax, NaN, NaN(1,n),...
"Marker", ".","MarkerSize", 8,...
"LineStyle", "none");
for k=1:n
set(h(k), ...
"XData", xData, ...
"YData", yData(:,k), ...
"DisplayName", yNames(k), ...
"Color", clrMap(k,:));
end
toc
Elapsed time is 0.092702 seconds.
cla(ax);
tic
h = plot(ax, xData, yData,...
"Marker", ".","MarkerSize", 8,...
"LineStyle", "none");
for k=1:n
set(h(k), ...
"DisplayName", yNames(k), ...
"Color", clrMap(k,:));
end
toc
Elapsed time is 0.066453 seconds.

类别

Help CenterFile Exchange 中查找有关 Discrete Data Plots 的更多信息

产品


版本

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by