Can plot markers be specified in an array?

I want to plot data from rows of a matrix using a separate marker for each row. I tried defining a string array and a cell array, like you can do with the legend command, but I got an error with both. It seems that the only way to do this is line by line, i.e., plot(x,row1,marker1,x,row2,marker2,...). Surely there is a better way.

2 Kommentare

GS
GS am 1 Sep. 2024
Thank you very much, Walter and Paul. This is what I was hoping for. I don't understand why they don't allow the plot command to accecpt the cell array as an argument in the first place, but this is the next best thing.
dpb
dpb am 1 Sep. 2024
Bearbeitet: dpb am 1 Sep. 2024
"... why they don't allow the plot command to accecpt the cell array as an argument"
What syntax specifically are thinking should work?
Perhaps the biggest reason for syntax being as it is is that plot <is an original member of MATLAB> and so predates all the niceties introduced later including cell arrays. Maintaining compatibility with existing code seriously restricts just how far away from the present syntax they can stray and still maintain the resulting code. plot() has been extended significantly with overloaded versions for the new data classes, etc., but the base argument syntax is simply not possible to revamp entirely

Melden Sie sich an, um zu kommentieren.

 Akzeptierte Antwort

Walter Roberson
Walter Roberson am 31 Aug. 2024

0 Stimmen

h = plot(x, DATAMATRIX.');
set(h, {'Marker'}, CELL_ARRAY_OF_MARKERS(:))
where CELL_ARRAY_OF_MARKERS must be a cell string with the same number of entries as the number of rows in DATAMATRIX
Notice that DATAMATRIX has to be transposed in the plot call: the rule is that columns of data become individual lines.

1 Kommentar

plot is smart enough to make each row of DATAMATRIX an individual line if that's the only way to be consistent with the number of elements of vector x
CELL_ARRAY_OF_MARKERS = {'+','o','x'};
DATAMATRIX = rand(3,4);
x = 1:4;
h = plot(x,DATAMATRIX); % no need for transpose
set(h,{'Marker'},CELL_ARRAY_OF_MARKERS(:))

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (3)

dpb
dpb am 31 Aug. 2024
Use the multiple-handle option with set; there are examples there.
NOTA BENE the property name and the properties must be passed as cell arrays, even when the property is just one value if the values aren't a single value. I called it a second time below to illustrate...
markers={'x';'+';'o'};
x=rand(5,3);
hL=plot(x);
set(hL,{'Marker'},markers)
set(hL,'Marker',markers)
Error using matlab.graphics.chart.primitive.Line/set
Error setting property 'Marker' of class 'Line':
Invalid enum value. Use one of these values: '+' | 'o' | '*' | '.' | 'x' | 'square' | 'diamond' | 'v' | '^' | '>' | '<' | 'pentagram' | 'hexagram' | '|' | '_' | 'none'.
The alternative way is that one can loop over the variables and pass the property value from an array as well; that way means don't forget to set hold on to not erase the initial lines with the subsequent ones in the loop.
Star Strider
Star Strider am 31 Aug. 2024
Both of those are possible (with the correct referencing), however I usually use a character array.
Try this —
marker = 'ox+p|sd';
x = 0:10;
y = randn(numel(marker), numel(x));
figure
plot(x,y(1,:),marker(1), x,y(2,:),marker(2), x,y(3,:),marker(3), x,y(4,:),marker(4), x,y(5,:),marker(5), x,y(6,:),marker(6), x,y(7,:),marker(7))
grid
figure
plot(x,y(1,:),['-',marker(1)], x,y(2,:),['-',marker(2)], x,y(3,:),['-',marker(3)], x,y(4,:),['-',marker(4)], x,y(5,:),['-',marker(5)], x,y(6,:),['-',marker(6)], x,y(7,:),['--',marker(7)])
grid
figure
hold on
for k = 1:numel(marker)
plot(x, y(k,:), '-', 'Marker',marker(k), 'DisplayName',"Marker "+string(marker(k)))
end
hold off
grid
ylim([min(ylim) max(ylim)*1.5])
legend('Location','best')
.

14 Kommentare

dpb
dpb am 31 Aug. 2024
Bearbeitet: dpb am 31 Aug. 2024
"I usually use a character array. ..."
Yeah, if you're passing in a loop or addressing in the multiple sets in a given call as the OP or your example, that's handy.
Is there a simple way to retrieve the default list? Must be in the default settings, I suppose, but I always have a heckuva a time trying retrieve/get the exact syntax/names right...I hadn't looked in ages, but it seems there are more possibilities than I remembered from days of yore; seems like there were only six or so "in the beginning"...
Paul
Paul am 31 Aug. 2024
Retrieve the default list of what? The default marker is 'none'.
dpb
dpb am 1 Sep. 2024
The list of available markers, sorry to have used 'default'
A klunky inelegant way... :)
%res=function getplotmarkers()
try
plot(1,1,'marker','fred','visible','off');
catch ME
close
tab=char(9);
markers=extractAfter(ME.message,'values: ');
markers=replace(markers,' | ',tab);
markers=strip(split(markers,tab));
markers=replace(string(markers),"'","");
markers=markers(1:end-1);
end
%end
%markers=getplotmarkers
markers
markers = 15x1 string array
"+" "o" "*" "." "x" "square" "diamond" "v" "^" ">" "<" "pentagram" "hexagram" "|" "_"
Paul
Paul am 1 Sep. 2024
List of available markers: Markers
dpb
dpb am 1 Sep. 2024
Yes, but that doesn't help programmatically when one is coding the array as here...one has to go copy/paste or type manually from the doc.
Paul
Paul am 1 Sep. 2024
I guess we were typing at the same time. I'm not aware of any (easy) programmatic way to get all allowable values of any graphics property. The list of markers generated above should inciude "none," which is a valid marker.
dpb
dpb am 1 Sep. 2024
Bearbeitet: dpb am 1 Sep. 2024
" it seems there are more possibilities than I remembered from days of yore; seems like there were only six or so "in the beginning"...
I have always wondered, however, why one can't specify any other character in the currently available character set if it didn't match the lookup mapping. Why not '$' or '@' or even the unicode graphic sets?
ADDENDUM
Of course, that then might break my above function in not generating the error... :)
For one thing, you wouldn't be able to specify certain characters. You could specify 'u' or 'w' but specifying 'v' would give you a downward-facing triangle instead of the character 'v'. [Changing that so that the letters that currently produce symbols, sxdvph, instead produce letters would be a significant backwards incompatibility.] Saying "20 out of 26 options work one way, you just have to remember the 6 exceptions" is annoying. [7 out of 12 months have 31 days. Without singing the mnemonic song to yourself, how many of the 5 exceptions can you remember immediately?]
There would also be ambiguity for certain characters -- if I specify 'b' in the line specification should that use 'b' as the marker or that you want a blue line? Would '-' give you a horizontal line as a marker or a solid line style?
For another, in which font would you expect the '$' marker to be written?
L = listfonts
L = 14x1 cell array
{'Arial' } {'Arial Black' } {'Arial Narrow' } {'Comic Sans MS' } {'Courier' } {'Courier New' } {'Georgia' } {'Helvetica' } {'Impact' } {'Terminal' } {'Times' } {'Times New Roman'} {'Trebuchet MS' } {'Verdana' }
axis([0 numel(L)+1 -1 3])
for k = 1:numel(L)
text(k, 0, '@', 'FontName', L{k});
text(k, 1, 'Q', 'FontName', L{k});
text(k, 2, '&', 'FontName', L{k});
text(k, 3, '$', 'FontName', L{k});
end
yticks(0:3)
yticklabels(["@", "Q", "&", "$"])
xticks(1:numel(L))
xticklabels(L)
For the most part those symbols look the same to my eye, except for Courier. But do all the symbols that you'd want to use as markers? And would line objects now need a FontName property to control whether or not the markers should be drawn in Courier or a different font?
dpb
dpb am 1 Sep. 2024
Bearbeitet: dpb am 1 Sep. 2024
"The list of markers generated above should inciude "none," which is a valid marker."
WAD. I chose to explicitly not consider it; it is in the list if one just removes the
markers=markers(1:end-1);
last line of the function.
dpb
dpb am 1 Sep. 2024
Bearbeitet: dpb am 1 Sep. 2024
@Steven Lord - I did specify that I would not replace the present alphanumeric set; just use the character if it isn't in the existing (or an extended set if were to be expanded). My thinking on the font/appearance is "it is what it is"; the user can opt out if doesn't like the appearance.
Parsing the triad would be a problem, indeed.
I have had in the past had a time or two that having a specific letter marker would have been useful to identify a given data set by the mnemonic. Of course, it can be done with text, so the complications in marker are sufficient to make it impractical, granted.
Of course, if the linestyle hadn't been grouped into the three-character triad form, then it wouldn't be so hard to parse.. :)
But, there certainly are far more serious issues to work on first; hatching patterns would be one that drove me batty for years while still consulting and limited to b/w printers only trying to present bar chart data to clients.
Eaty way to get the permitted markers:
h = plot(nan);
allowed = set(h,'Marker')
allowed = 16x1 cell array
{'+' } {'o' } {'*' } {'.' } {'x' } {'square' } {'diamond' } {'v' } {'^' } {'>' } {'<' } {'pentagram'} {'hexagram' } {'|' } {'_' } {'none' }
dpb
dpb am 1 Sep. 2024
Bearbeitet: dpb am 2 Sep. 2024
Slick, Walter! I shoulda' thought of that years ago...use the feature frequently at the command line...so we can shorten the functional form significantly...
function markers=getplotmarkers()
% return list of allowable plot() markers as cellstr array
hF=figure('Visible','off'); % create figure, no see'um distraction
hAx=axes(hF); % and an axes in the specific figure for sure
hL=plot(hAx,nan); % a dummy line handle in that axes
markers=set(hL,'Marker'); % set w/o value returns available list if enumerated
delete(hL); delete(hAx); close(hF); % clean up after oneself
end
dpb
dpb am 1 Sep. 2024
@Steven Lord -- Actually, I was thinking of only via the line 'Marker','char' form, not as part of a linestyle triad; would that not eliminate the conflict? The triads remain as they are being required to be one of the accepted character set for style, marker, color; just don't prevent/screen other characters from displaying what they are if explicitly set. Granted, the internal checking logic undoubtedly uses the same screeening, but we're talking hypothetical here... :)

Melden Sie sich an, um zu kommentieren.

Umar
Umar am 1 Sep. 2024

0 Stimmen

Hi @GS,

To address your query regarding, “ I want to plot data from rows of a matrix using a separate marker for each row. I tried defining a string array and a cell array, like you can do with the legend command, but I got an error with both. It seems that the only way to do this is line by line, i.e., plot(x,row1,marker1,x,row2,marker2,...). Surely there is a better way.”

Please see my response to your comments below.

First, create a sample data matrix dataMatrix with 5 rows and 10 columns filled with random values using rand(). I defined the variable x to represent the x-axis values, which correspond to the columns of the matrix. Then, name a cell array as markers containing different marker styles: circles, squares, triangles, diamonds, and crosses which will allow to assign a unique marker to each row of the matrix. Then, initiate a new figure and use hold on to ensure that all plots are displayed on the same graph without overwriting previous plots. Loop through rows by iteration row of the dataMatrix. Inside the loop, call the plot() function to plot the current row against the x-values, using the corresponding marker from the markers array and set the DisplayPropertyName to label each row for the legend. After the loop, call hold off to stop adding to the current plot. Then, label the axes, set a title for the plot, and display the legend using legend show and use grid on to enhance the readability of the plot.

Please see attached.

If you have any further questions, please let us know.

Kategorien

Mehr zu Data Type Identification finden Sie in Hilfe-Center und File Exchange

Produkte

Version

R2020b

Gefragt:

GS
am 31 Aug. 2024

Bearbeitet:

dpb
am 2 Sep. 2024

Community Treasure Hunt

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

Start Hunting!

Translated by