0
$\begingroup$

The problem is a bit tricky, I will try to be as clear as possible. I have several lists (let's call them x, y, z and k), all of the same length, and where the i-th value of each list corresponds to a single observation (so for instance x[[3]], y[[3]], z[[3]] and k[[3]] are the values of four variables for the third observation). What I want to do is a scatter plot, where the x-axis reports the values of x and the y-axis the values of y. Now, for each pair (x[[i]], y[[i]]) I want a red dot if z[[i]] > k[[i]], and a black dot otherwise. Additional issue: for the first observations, the list k is empty, so I want to plot a red dot for such observations. Any idea on how is it possible to do it?

$\endgroup$
2
  • 1
    $\begingroup$ Hint: You can style individual points in ListPlot using Style[{x, y}, color]. $\endgroup$
    – C. E.
    May 27, 2020 at 14:16
  • $\begingroup$ That is very helpful, I will have a try with that. Thank you. $\endgroup$ May 27, 2020 at 14:19

2 Answers 2

4
$\begingroup$

Here is an example with made up data:

Clear[y, z, k]
x = Range[20];
{y, z, k} = RandomInteger[{-10, 10}, {3, 20}];

ListPlot[
  MapThread[Style[{#1, #2}, If[#3 > #4, Red, Black]] &, {x, y, z, k}],
  PlotRange -> All,
  PlotStyle -> PointSize[0.02]
]

formatted points


For your second part ("Additional issue: for the first observations, the list k is empty, so I want to plot a red dot for such observations."), you should really provide a sample of your data. Any answer would depend on its precise structure.

$\endgroup$
5
  • $\begingroup$ That is perfect, thank you! $\endgroup$ May 27, 2020 at 14:30
  • $\begingroup$ For the last part you could just PadLeft the kkkkk... list with some non-number element e.g {} to the same size as any of the the xxxxx... or yyyyy.... zzzzz... lists before transposing to {{x,y,z,{}},{x,y,z,{}},{x,y,z,k},{x,y,z,k}... etc}. Then change your style function to only apply if #4 is not {}. $\endgroup$
    – flinty
    May 27, 2020 at 14:33
  • $\begingroup$ Thank you for the added comment, your code actually worked nice as it is :) $\endgroup$ May 27, 2020 at 19:57
  • $\begingroup$ I have an additional question. What if I would like to use different shapes instead of different colours? $\endgroup$ Jun 5, 2020 at 9:21
  • $\begingroup$ @MarcoB can you help me? $\endgroup$ Jun 7, 2020 at 12:11
2
$\begingroup$

Generate random data with first two values of k missing.

SeedRandom[1234]

{x, y, z, k} = 
 ReplacePart[RandomReal[{0, 10}, {4, 20}], {{4, 1}, {4, 2}} -> Missing]

Just use Graphics primitives to make the scatter plot.

Legended[Graphics[{AbsolutePointSize[
    4], {If[#[[4]] === Missing || #[[3]] > #[[4]], Red, Black], 
      Point[#[[1 ;; 2]]]} & /@ Transpose[{x, y, z, k}]},
  Frame -> True,
  FrameLabel -> (Style[#, 14, Bold, Italic] & /@
      {"x", "y"} /. 
     s_String :> Subscript[s, "i"]),
  AspectRatio -> 1/GoldenRatio],
 PointLegend[{Red, Black}, {"z" > "k", "z" <= "k"} /. 
   s_String :> Subscript[s, "i"]]]

enter image description here

EDIT: Alternatively, you get the same plot using GatherBy with the criteria to generate two data sets.

plotData = #[[All, 1 ;; 2]] & /@ 
   GatherBy[Transpose[{x, y, z, k}], #[[4]] === Missing || #[[3]] > #[[4]] &];

ListPlot[plotData,
 PlotStyle -> {Red, Black},
 Frame -> True,
 FrameLabel -> (Style[#, 14, Bold, Italic] & /@
     {"x", "y"} /. 
    s_String :> Subscript[s, "i"]),
 PlotLegends -> {"z" > "k", "z" <= "k"} /.
  s_String :> Subscript[s, "i"]]
$\endgroup$
3
  • $\begingroup$ I am sorry, I just notice I did not answer you. Thank you for your answer. I just have an additional question: what if I would like to do the same, but using different shapes instead of different colours? $\endgroup$ Jun 7, 2020 at 12:12
  • $\begingroup$ Use the option PlotMarkers, e.g., PlotMarkers -> Automatic $\endgroup$
    – Bob Hanlon
    Jun 7, 2020 at 15:24
  • $\begingroup$ Thank you! I cannot believe it was that easy, I was trying much more complicated stuff. $\endgroup$ Jun 9, 2020 at 7:41

Your Answer

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

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