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$
6
  • 2
    $\begingroup$ Why it's a problem to add x coordinate? $\endgroup$
    – swish
    Commented Jan 29, 2017 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
    Commented Jan 29, 2017 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
    Commented Jan 29, 2017 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
    Commented Jan 29, 2017 at 2:04
  • 1
    $\begingroup$ The universal approach is to write a custom function. $\endgroup$
    – m_goldberg
    Commented Jan 29, 2017 at 2:07

1 Answer 1

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$
1
  • $\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
    Commented Jan 29, 2017 at 2:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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