# ListPlot with different color options

Let's define some sample data

data = {{-3, -1}, {-2, -1}, {-1, -1}, {-0.2, -0.2}, {0, 0}, {0.5, 0.5},
{2, 2}, {3, 2}, {4, 2}};


and create the corresponding list plot

L0 = ListPlot[data, Joined -> True, PlotStyle -> {Black, Thick}]


Now, I want the following: change the color at different segments of the thick line. For example:

• for $-2.4 < x < -1.1$ ---> red thick
• for $-0.2 < x < 0.94$ ---> blue thick
• for $2.22 < x < 3.4$ ---> green thick
• in all other cases ---> black thick

IMPORTANT NOTE: The real data contain thousands of pairs which cannot be separated into sections. Only the intervals on the x axis are known. So, I want a continuous line with different colors in each segment.

What would be an elegant and quick way to do this?

• The simplest? Separate the data into sections, run ListPlot[sectioned, PlotStyle -> {Directive[Thick, Blue], Directive[Thick, Blue], Directive[Thick, Green], Directive[Thick, Black]}] where the styles in PlotStyle are in the correct order. – rcollyer Oct 10 '16 at 17:59
• Should be doable with the judicious use of ColorFunction and Piecewise[]. – J. M. will be back soon Oct 10 '16 at 18:03
• @rcollyer It's not that simple! The real data contain thousands of pairs which cannot be separated into sections. Only the intervals on the $x$ axis are known. So, I want a continuous line with different colors in each segment. – Vaggelis_Z Oct 10 '16 at 18:03
• @J.M. i thought that too but when you try it, Mathematica blends the colors over and does not make a sharp border.. – Julien Kluge Oct 10 '16 at 18:09
• You're correct, the boundary points represent a problem. I like the Mesh solutions propose below. Far simpler. – rcollyer Oct 10 '16 at 18:43

data = {{-3, -1}, {-2, -1}, {-1, -1}, {-0.2, -0.2}, {0, 0}, {0.5, 0.5},
{2, 2}, {3, 2}, {4, 2}};

ListPlot[data, Joined -> True, PlotStyle ->Thick,
(* MeshFunctions -> {# &},*)
Mesh -> {{-2.4, -1.1, -0.2, 0.94, 2.22, 3.4}},
MeshStyle -> PointSize[0],
MeshShading -> Riffle[{Red, Blue, Green}, Black, {1, -1, 2}]]


• Great answer! What if there is no gap between blue and green? Will it still work or there will be a black point? – BlacKow Oct 10 '16 at 18:47
• I like that. I wondered why you used MeshFunctions->{#&}. Is there a reason for that? – Julien Kluge Oct 10 '16 at 18:51
• @BlacKow, this works only for the case with no overlaps. If the list of breakpoints have duplicate elements as in {-2.4, -1.1, -0.2, 0.94, .94, 3.4} then you can use MeshShading->{Black, Red, Black, Blue, Green} – kglr Oct 10 '16 at 18:55
• @JulienKluge, good point; the default value of MeshFunctions is #&, so it is redundant. – kglr Oct 10 '16 at 18:58
• @Vaggelis_Z, it inserts Black in every other position in the list {Red,Blue, Green} starting from position one. Without it Riffle[{Red,Blue, Green}, Black] would give {Red, Black,Blue, Black, Green}. See Riffle – kglr Oct 10 '16 at 19:11

We use an unscaled ColorFunction with a Piecewise which uses your definitions. Interestingly one have to alter the Mesh-settings to allow a sharp color-border otherwise it will blend over.

L0=ListPlot[data,Joined->True,PlotStyle->Thick,ColorFunction->Function[{x,y},Piecewise[{{Red,-2.4<x<-1.1},{Blue,-0.2<x<0.94},{Green,2.22<x<3.4}},Black]],ColorFunctionScaling->False,Mesh->200,MeshShading->{Automatic},MeshStyle->None]


• Is it just my impression or the middle part is not so smooth? I see it like a bunch of dots... – Vaggelis_Z Oct 10 '16 at 18:35
• Uhm well, it looks good to me on my machine. Try to Increase the Mesh-option. Can you show a screenshot? – Julien Kluge Oct 10 '16 at 18:38
• The Mesh-option does not have any affect. Try to enlarge the image you posted and you will see that the middle line is not a real straight line! It looks like a join of dots or something else! – Vaggelis_Z Oct 10 '16 at 18:43
• I'm on OSX, MMA 11.0.0.0 and I see the same behavior, but only for this answer. Other options show a smooth curve. – N.J.Evans Oct 10 '16 at 19:07

As alternative you can follow up idea of separation. Since we don't know if you have the endpoints of your regions in your data set , we can use Interpolation and then break it up into several pieces.

limitF[f_, {xmin_, xmax_}] :=
Piecewise[{{f[#], xmax > # > xmin}}, Infinity] &;
data = {{-3, -1}, {-2, -1}, {-1, -1}, {-0.2, -0.2}, {0, 0}, {0.5,
0.5}, {2, 2}, {3, 2}, {4, 2}};
fun = Interpolation[data, InterpolationOrder -> 1];
separated =
limitF[fun, #] & /@ {{-2.4, -1.1}, {-0.2, 0.94}, {2.2, 3.4}};


So separated is list of functions that present fun in different regions.

Plot[Evaluate[{fun[x]}~Join~(#[x] & /@ separated)], {x, -3, 4},
PlotStyle -> {Directive[Thick, Black], Directive[Thick, Red],
Directive[Thick, Blue], Directive[Thick, Green]}]