# Implementing a LineStyleFunction for line plots

I have data in the form:

{{0, 3, 4}, {1, 3, -1}, {2, 4, -1}, ...}


and I would like to implement something similar to ColorFunction for the style of a line. Basically I would like to plot a standard line plot using the first two entries of each point {x, y, ..}, and then decide on the line style using the 3rd {.., .., z}.

Specifically I would like to plot dashed lines when the 3rd entry is positive and filled lines when negative, formed as one continuous curve.

EDIT: to clarify, there will be large regions where the 3rd entry is consistently positive or negative, so its purpose is to set the style for those regions. This method wouldn't really work for situations where the 3rd value oscillates between the two.

Many thanks, Hemmer

• Welcome to Mathematica.SE! It is not very clear what you are trying to obtain. The 3rd entry is specific for a certain point, but you want to specify the style of a line segment that connects two points. Which two points? – VLC Oct 8 '12 at 15:51
• Hi there. I hadn't actually given thought to which two, I guess applying the line between the current point and the next. As the are large contiguous regions of positive & negative, I hadn't worried about that! – Hemmer Oct 8 '12 at 16:47

This is my interpretation of your question: the 3rd element of a point specifies the style of the line that connects that point with the next one.

data = Table[{i, RandomInteger[{1, 10}], RandomChoice[{-1, 1}]}, {i, 20}];
setsN = DeleteCases[Table[If[data[[i, 3]] < 0, data[[i ;; i + 1, {1, 2}]], {}], {i,
Length[data] - 1}], {}];
setsP = DeleteCases[Table[If[data[[i, 3]] > 0, data[[i ;; i + 1, {1, 2}]], {}], {i,
Length[data] - 1}], {}];
Show[
ListLinePlot[setsN, PlotStyle -> {{Thick, Black}}],
ListLinePlot[setsP, PlotStyle -> {{Thick, Black, Dashed}}]
] • Thanks, this is what I was looking for. I had wondered if there was an inbuilt way to do this without manually processing the data beforehand, but this will certainly do the job! I guess the style of the line doesn't map naturally to continuous functions in the same way a ColorFunction might. – Hemmer Oct 8 '12 at 16:49
• @Hemmer You're welcome. Now that is clear what is your desired output there might be someone else that could provide a more direct approach to the question. – VLC Oct 8 '12 at 16:50

## Correction!

Sorry for misunderstanding. Here is a updated code

Options[plot] = Options[ListPlot];
plot[data_, options : OptionsPattern[ListPlot]] := Block[{line},
line[{pt1_, pt2_}] := Module[
{z},
z = pt1[];
{
If[z >= 0, Dashed, Thickness[0.0045]],
If[z >= 0, Orange, Cyan],
Line[(#[[1 ;; 2]]) & /@ {pt1, pt2}]
}
];
Show[ListPlot[data[[All, 1 ;; 2]], options],
Graphics[line[#] & /@ Partition[data, 2, 1]]
]
]


Now we test it. We intentionally use PlotStyle -> None to hide the data points!

fun[x_] := Sin[13 x] + Cos[7 x];
data = Table[{i, a = fun[ i]; a, If[ a >= 0, 1, -1]}, {i, - Pi, Pi,2. Pi/120}];
plot[data, Frame -> True, Axes -> False, PlotStyle -> None] It seems to me that using Graphics would be easier than messing with LinePlots.

We can define any number of styles with a function:

ClearAll[lineStyle];
lineStyle[z_] /; z < 0 := {Orange, Dashed};
lineStyle[z_] /; z > 0 := {Blue, Thick};
lineStyle[z_] := {Black};


Then create a function to plot data using this style:

ClearAll[styledPlot];
styledPlot[data_, o : OptionsPattern[]] := Graphics[Partition[data, 2, 1] /.
{{x1_, y1_, z1_}, {x2_, y2_, z2_}} :> Append[lineStyle[z1], Line[{{x1, y1}, {x2, y2}}]],
Evaluate[FilterRules[{o}, Options[Graphics]]]]


In use:

styledPlot[
Table[{i, RandomInteger[{1, 10}], RandomInteger[{-5, 5}]}, {i, 20}],
Frame -> True, PlotLabel -> "Styled"] • Might be better to use something like lineStyle[z_?Negative] or lineStyle[z_?Positive] in the definitions. no? – J. M. will be back soon Oct 8 '12 at 23:36
• @J.M. I was trying to show how to be a bit more general than just positive or negative. – wxffles Oct 8 '12 at 23:49

Using a minor modification of this answer to another question, Mesh, MeshFunctions, MeshStyle and MeshShading options can be used to specify the directives for different pieces of the lines in ListLinePlot.

Data:

 breaks = Join[{0}, Sort@RandomInteger[{2, 99}, 5], {100}];
i = 2; arg3 = (j = i++; ConstantArray[(-1)^j, {#}]) & /@ Differences[breaks];
data = {Range, RandomInteger[100, {100}], Flatten@arg3} // Transpose;


Calculate mesh points:

 meshpoints = Most@Accumulate[Length /@ Split[data, Last[#1] == Last[#2] &]];


... plot:

ListLinePlot[data[[All, ;; 2]], PlotStyle -> Blue,ImageSize -> 450,
Mesh -> {meshpoints},
MeshStyle -> None,
MeshFunctions -> (#1 &),
MeshShading -> {Thick, Directive[Thick, Dashed]}] • I think that this approach fails if the entries in 3rd position are not part of contiguous regions of positive or negative values. And, the assignment on which segments are dashed and which continuous is arbitrary because it depends on the category of the first segment. – VLC Oct 9 '12 at 9:29
• @VLC, both concerns can be fixed easily: using .01 + meshpoints instead of meshpoints is enough to care of the cases where the third column values alternate between positive and negative at every observation. And reversing the list Thick, Directive[Thick, Dashed] based on the sign of data[[1,1]], that is, using omething like MeshShading -> Switch[Sign[data[[1, 3]]], 1, Identity@#, _, Reverse@#] &@{Thick, Directive[Thick, Dashed]} takes care of the second concern. – kglr Oct 11 '12 at 19:44