2
$\begingroup$

I want to color each point in ListPlot using custom markers when there are only values of the points, i.e. the data is in the form {1,2,3,...}. There are many related questions (e.g. here and here), but the solutions are either to use data in the form {x,y}, convert it to the list of lists, and then effectively color each subplot separately

data1 = {{{1, 2}, Red}, {{2, 3}, Blue}};
ListPlot[
   List /@ data1[[;; , 1]], 
   PlotMarkers -> 
      Apply[Graphics[{#, Rectangle[]}, ImageSize -> 15] &, List /@ data1[[;; , 2]], {1}]
]

or to color each point using Style, in which case using custom markers doesn't work.

data2 = {Style[2, Red], Style[3, Blue]};
ListPlot[data2, PlotMarkers -> Graphics[{Rectangle[]}, ImageSize -> 15]]

Is there a solution when the data doesn't have the x coordinate?

$\endgroup$
  • 2
    $\begingroup$ Why it's a problem to add x coordinate? $\endgroup$ – swish Jan 29 '17 at 1:04
  • $\begingroup$ @swish it isn't, but I'm interested in a more general solution, that doesn't require inserting dummy coordinates. If anything, DataRange doesn't work with x inserted, so you will need a new workaround there and so on. $\endgroup$ – Stitch Jan 29 '17 at 1:12
  • $\begingroup$ Why didn't put the requirement that you wanted to specify the data range in your question? Very bad form not to do that. $\endgroup$ – m_goldberg Jan 29 '17 at 1:38
  • 1
    $\begingroup$ @m_goldberg Well, data range was just an example, I was thinking in more general terms when something else might not work as well. For my particular example, this will work, but the idea was to understand a more universal approach. $\endgroup$ – Stitch Jan 29 '17 at 2:04
  • 1
    $\begingroup$ The universal approach is to write a custom function. $\endgroup$ – m_goldberg Jan 29 '17 at 2:07
5
$\begingroup$

I'm with swish. I think it's easy to add the x-coordinate.

data = {{2, Red}, {3, Blue}, {1, Green}};
Module[{pts, markers},
  pts = MapThread[{{#1, #2}} &, {Range @ Length[data], data[[All, 1]]}];
  markers = 
    Graphics[{#, Rectangle[]}, ImageSize -> 15] & @@@ List /@ data[[All, 2]];
  ListPlot[pts, PlotMarkers -> markers]]

plot

Update

If you want to specify the plot range, then define a custom version of ListPlot. Like so:

myListPlot[data_, min_, max_] :=
  Module[{xcoords, pts, markers},
    xcoords = Subdivide[min, max, Length[data] - 1];
    pts = MapThread[{{#1, #2}} &, {xcoords, data[[All, 1]]}];
    markers = 
      Graphics[{#, Rectangle[]}, ImageSize -> 15] & @@@ List /@ data[[All, 2]];
    ListPlot[pts, PlotMarkers -> markers]]

myListPlot[data, 10, 20]

plot

plot

$\endgroup$
  • $\begingroup$ Makes sense. I tend to agree it is a good solution using x coordinate. There might be other options that wouldn't work, but I will leave those cases to future questions. $\endgroup$ – Stitch Jan 29 '17 at 2:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.