Plot multiple data sets fast - fastest/latest/efficient method up to R2023a
10 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
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:
- Concatenate the data, plot all points once -> not applicable, only useful for people who draw custom grids, or geographic features
- 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.
- 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 comentario
Mann Baidi
el 16 de Ag. de 2023
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);
Respuestas (2)
Siraj
el 23 de Ag. de 2023
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 comentarios
Siraj
el 23 de Ag. de 2023
Editada: Siraj
el 23 de Ag. de 2023
@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
el 23 de Ag. de 2023
Editada: Bruno Luong
el 23 de Ag. de 2023
@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
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
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
0 comentarios
Ver también
Categorías
Más información sobre Discrete Data Plots en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!