# Use different markers/colors in logarithmic plot depending on sign

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.

• 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! – Lukas Jun 17 '15 at 7:07

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})]


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

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

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]]


• Thanks for this answer, especially for your explanation. – Lukas Jun 17 '15 at 6:53

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}
]


• 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. – Lukas Jun 17 '15 at 7:02
• 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. – N.J.Evans Jun 17 '15 at 15:06

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]]
]


• @Lukas, My pleasure:-) Glad to know you like it. – xyz Jun 17 '15 at 7:38

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
]