10
$\begingroup$

Suppose you have the dataset

xData = Table[i, {i, 1, 30}];
yData = RandomReal[{0.995, 1.005}, 30];

and want to plot the difference of yData-1 on a ListLogPlot.

ListLogPlot[Transpose[{xData, yData - 1}], Joined -> True, Mesh -> All]

Of course, there will be negative differences, hence not being plotted. If the differences' signs were unimportant one could just plot Abs[yData-1]. However, if the sign is important: What is a (I am sure there must be something) nice way to e.g. plot the Abs but use different markers for different signs. The only way I can come up with is pre-processing the data into two sets corresponding to the signs and then plot both seperately into the same graph.

Edit: I decided to accept MichaelE2's answer because I did not know anything about VertexColor and it could be very useful for future plotting issues. However, also all other answers are great solutions and I don't mean to depreciate their value by not accepting them - I just think that one answer should be accepted to "close" the question.

$\endgroup$
1
  • $\begingroup$ There are several very good answers so far. I would like to accept multiple ones, however not possible. So, I will just wait a few days to (i) wait for others answers (ii) think about which I will finally accept. Thanks to everyone so far! $\endgroup$
    – Lukas
    Jun 17, 2015 at 7:07

5 Answers 5

8
$\begingroup$

You can use VertexColors to color the individual points, since the points are all in a single Point in order.

ListLogPlot[Transpose[{xData, Abs[yData - 1]}], Joined -> True, Mesh -> All] /. 
 Point[p_] :> 
   Point[p, VertexColors -> (Sign[yData - 1] /. {1 -> Black, -1 -> Red, 0 -> Blue})]

Mathematica graphics

Threw in the 0 case even though 0 won't be plotted by ListLogPlot. One could have it print a warning, too.

$\endgroup$
2
  • $\begingroup$ Nice solution. I did not know that VertexColors exists. Could be helpful in future $\endgroup$
    – Lukas
    Jun 17, 2015 at 6:58
  • 1
    $\begingroup$ @Lukas Thanks, and VertexColors is a more efficient way to color points, esp. when you have Point[<long list of points>, VertexColors -> colors]. $\endgroup$
    – Michael E2
    Jun 17, 2015 at 12:24
9
$\begingroup$

The colors can be determined by the sign separately like this:

colors = Sign[yData - 1] /. {1 -> Blue, -1 -> Red};

In order to change the color of the individual markers we have to change the Graphics object that ListLogPlot generates. We can view that expression using

plot = ListLogPlot[
 Transpose[{xData, Abs[yData - 1]}],
 Joined -> True, Mesh -> All
 ];
plot // FullForm

We notice that the points are drawn by using the Point graphics primitive, like this:

Point[{{x1,y1},{x2,y2},...}]

In order to define the colors of the markers separately we have to create one Point primitive for each marker. We can do that using Thread:

Thread@Point[{{x1,y1},{x2,y2},...}]
(* Out: {Point[{x1,y1}],Point[{x2,y2}],...} *)

Now we can use Riffle to insert the colors.

plot /. p : Point[_] :> Riffle[colors, Thread[p]]

Mathematica graphics

$\endgroup$
1
  • $\begingroup$ Thanks for this answer, especially for your explanation. $\endgroup$
    – Lukas
    Jun 17, 2015 at 6:53
7
$\begingroup$

Fundamentally this isn't much different than what you're suggesting, as far as splitting the data into positive and negative parts,

xData = Table[i, {i, 1, 30}];
yData = RandomReal[{0.995, 1.005}, 30];

ListLogPlot[
 {{#1, Abs@#2}} & @@@ Transpose@{xData, yData - 1},
 PlotStyle -> (yData - 1) /. {x_Real /; Sign[x] == -1 :> Red, 
   x_Real :> Black}
 ]

enter image description here

$\endgroup$
2
  • $\begingroup$ thanks for your answer, as well. That is indeed quite similar to what I thought about. However, I did not know that it's possible to use conditionals for PlotStyle. $\endgroup$
    – Lukas
    Jun 17, 2015 at 7:02
  • $\begingroup$ It's not actually using conditionals for the plot style, it's just replacing the elements of yData with the appropriate color. What is actually fed to PlotStyle is a list of RGBColors. $\endgroup$
    – N.J.Evans
    Jun 17, 2015 at 15:06
3
$\begingroup$

I propose the Epilog option

xData = Table[i, {i, 1, 30}];
yData = RandomReal[{0.995, 1.005}, 30];

(*Construct the colors and the point objects*)

pts = Point /@ Transpose[{xData, Log@Abs[yData - 1]}];
colors = Sign[yData - 1] /. {1 -> Blue, -1 -> Red};

(*visulization*)

ListLogPlot[
 Transpose[{xData, Abs[yData - 1]}], Joined -> True, 
  Epilog -> Prepend[Riffle[colors, pts], PointSize[Medium]]
]

enter image description here

$\endgroup$
1
  • $\begingroup$ @Lukas, My pleasure:-) Glad to know you like it. $\endgroup$
    – xyz
    Jun 17, 2015 at 7:38
2
$\begingroup$

Style can be used directly on elements of several different plot types.

ListPlot[
  Transpose[{xData, yData - 1}] /.
    {x_, y_?Negative} :> Style[{x, -y}, Red], 
  Joined -> True,
  Mesh -> All,
  ImageSize -> 500
]

enter image description here

$\endgroup$

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.