4
$\begingroup$

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

enter image description here

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?

Many thanks in advance!

$\endgroup$
  • $\begingroup$ 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. $\endgroup$ – rcollyer Oct 10 '16 at 17:59
  • $\begingroup$ Should be doable with the judicious use of ColorFunction and Piecewise[]. $\endgroup$ – J. M. will be back soon Oct 10 '16 at 18:03
  • $\begingroup$ @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. $\endgroup$ – Vaggelis_Z Oct 10 '16 at 18:03
  • $\begingroup$ @J.M. i thought that too but when you try it, Mathematica blends the colors over and does not make a sharp border.. $\endgroup$ – Julien Kluge Oct 10 '16 at 18:09
  • $\begingroup$ You're correct, the boundary points represent a problem. I like the Mesh solutions propose below. Far simpler. $\endgroup$ – rcollyer Oct 10 '16 at 18:43
6
$\begingroup$
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}]]

Mathematica graphics

$\endgroup$
  • $\begingroup$ Great answer! What if there is no gap between blue and green? Will it still work or there will be a black point? $\endgroup$ – BlacKow Oct 10 '16 at 18:47
  • 1
    $\begingroup$ I like that. I wondered why you used MeshFunctions->{#&}. Is there a reason for that? $\endgroup$ – Julien Kluge Oct 10 '16 at 18:51
  • $\begingroup$ @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} $\endgroup$ – kglr Oct 10 '16 at 18:55
  • 1
    $\begingroup$ @JulienKluge, good point; the default value of MeshFunctions is #&, so it is redundant. $\endgroup$ – kglr Oct 10 '16 at 18:58
  • 1
    $\begingroup$ @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 $\endgroup$ – kglr Oct 10 '16 at 19:11
3
$\begingroup$

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]

enter image description here

$\endgroup$
  • $\begingroup$ Is it just my impression or the middle part is not so smooth? I see it like a bunch of dots... $\endgroup$ – Vaggelis_Z Oct 10 '16 at 18:35
  • $\begingroup$ Uhm well, it looks good to me on my machine. Try to Increase the Mesh-option. Can you show a screenshot? $\endgroup$ – Julien Kluge Oct 10 '16 at 18:38
  • $\begingroup$ 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! $\endgroup$ – Vaggelis_Z Oct 10 '16 at 18:43
  • $\begingroup$ 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. $\endgroup$ – N.J.Evans Oct 10 '16 at 19:07
2
$\begingroup$

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

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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