7
$\begingroup$

I have data that I would like to graph that alternates colors when a condition is identified. For example, say I have the following list:

templist={{5,1},{5,2},{5,3},{1,4},{1,5},{1,6},{4,7},{4,8},{5,9},{5,10}};

where the first value in each point is a categorical identifier and the second value is what I would like to graph. Is there a way to make a function that will graph the second values in the data and toggle between two colors when the categorical value changes?

I have tried to use the show function, but I'm unsure of how to do that properly in this example as the number of different categorical values will differ for each data set I'd like to apply this to.

EDIT: I would like to use something akin to ListLinePlot as the practical application of this function will involve trending data.

$\endgroup$
2
  • $\begingroup$ look at SplitBy $\endgroup$
    – george2079
    Jun 16, 2017 at 11:44
  • $\begingroup$ @george2079 I have looked at SplitBy. My problem isn't so much with the separating of the values but the coloring aspect of the graph(s). $\endgroup$ Jun 16, 2017 at 11:51

4 Answers 4

5
$\begingroup$
list = 
   {{5, 1}, {5, 2}, {5, 3}, {1, 4}, {1, 5}, {1, 6}, {4, 7}, {4, 8}, {5, 9}, {5, 10}}

cat = Split[First /@ list];

col = Flatten@Transpose[{cat[[1 ;; ;; 2]] /. x_Integer -> Blue, 
    cat[[2 ;; ;; 2]] /. x_Integer -> Red}];

ListLinePlot[
 Last /@ list,
 GridLines -> Automatic,
 Mesh -> Length@list - 1,
 MeshShading -> col,
 PlotStyle -> Directive[PointSize[0], Thick]]

enter image description here

$\endgroup$
5
  • $\begingroup$ This works partially well, but I'd like the color change to be maintained through the new part instead of only on the first different value. $\endgroup$ Jun 16, 2017 at 12:10
  • $\begingroup$ Is this now what you have in mind? $\endgroup$
    – eldo
    Jun 16, 2017 at 12:44
  • $\begingroup$ This is indeed what I was looking for. $\endgroup$ Jun 16, 2017 at 12:55
  • $\begingroup$ @eldo What is your Mma version? I'm using 11.1 and your PointSize directive is not suppressing the mesh for me. $\endgroup$
    – Alan
    Jun 16, 2017 at 13:29
  • $\begingroup$ I have version 10.0 $\endgroup$
    – eldo
    Jun 16, 2017 at 15:53
2
$\begingroup$
templist = {{5, 1}, {5, 2}, {5, 3}, {1, 4}, {1, 5}, {1, 6}, {4, 
    7}, {4, 8}, {5, 9}, {5, 10}};
catpts = MapIndexed[Append[#1, First@#2] &, templist]
cats = SplitBy[catpts, First]
data = Map[Reverse@*Rest, cats, {2}]
ListLinePlot[data, PlotStyle -> {Red, Blue}]

enter image description here

$\endgroup$
1
$\begingroup$

First prepare the data, separating it into different lists according to the labels. In this process we also add the x coordinate to each point, so that ListPlot can correctly draw them regardless of their position in a list:

templist = {{5, 1}, {5, 2}, {5, 3}, {1, 4}, {1, 5}, {1, 6}, {4, 7}, {4, 8}, {5, 9}, {5, 10}};

dataByLabel = Association[(# -> {}) & /@ Union[First /@ templist]];
Do[
  AppendTo[dataByLabel[templist[[idx, 1]]], {idx, templist[[idx, 2]]}],
  {idx, Range@Length@templist}
  ];

This gathers the data in the association dataByLabel. To plot it as requested just use ListPlot:

ListPlot @ Values @ dataByLabel

With this method is also easier to successively handle the data, as they are now nicely gathered in dataByLabel.

$\endgroup$
1
  • $\begingroup$ This is definitely along the lines of what I'm looking for, but is there any way to make a line graph out of this? If I change the graph function to ListLinePlot the line is only the first color. $\endgroup$ Jun 16, 2017 at 12:12
0
$\begingroup$

While @eldo's answer was initially useful to me, I found that the color transitions not being exactly on the point that they transitioning on was quite irritating for me. When using data with a size of thousands, it's an irrelevant factor, but I came up with a way that negates this problem. The downside is that the image takes significantly longer to graph the more categories there are, but that should also be a moot point with smaller sample sizes.

The first block is only variable assignment.

templist = {{5, 1}, {5, 2}, {5, 3}, {1, 4}, {1, 5}, {1, 6}, {4, 
    7}, {4, 8}, {5, 9}, {5, 10}};
lowerBound = 1; upperBound = 1; graphInfo = {};    

The second block creates a list containing the lower and upper bounds of each sublist of the data, as well as the color for that sublist.

For[i = 1, i < Length[templist], i++,
 If[templist[[i, 1]] != templist[[i + 1, 1]],
  {AppendTo[
    graphInfo, {lowerBound, upperBound, 
     If[Mod[Length[graphInfo], 2] == 1, Green, Red]}], 
   lowerBound = upperBound, upperBound++},
  upperBound++]]

graphInfo
{{1, 3, RGBColor[1, 0, 0]}, {3, 6, RGBColor[0, 1, 0]}, {6, 8, 
  RGBColor[1, 0, 0]}, {8, 10, RGBColor[0, 1, 0]}}

The third and fourth blocks of code create another list that contains the actual data as well as the color for each sublist.

AppendTo[graphInfo, {lowerBound, upperBound, 
   If[Last[graphInfo][[3]] == Red, Green, Red]}];
graphsData = {};
For[j = 1, j <= Length[graphInfo], j++, 
 AppendTo[graphsData, {Take[
    templist[[All, 2]], {graphInfo[[j, 1]], graphInfo[[j, 2]]}], 
   graphInfo[[j, 3]]}]]

counter = 0;
For[l = 1, l <= Length[graphsData], 
 l++, {graphsData[[l, 
     1]] = {Table[{counter + i, graphsData[[l, 1, i]]}, {i, 
      Length[graphsData[[l, 1]]]}]}, 
  counter = counter + Length[graphsData[[l, 1, 1]]] - 1}]

graphsData
{{{{{1, 1}, {2, 2}, {3, 3}}}, RGBColor[
  1, 0, 0]}, {{{{3, 3}, {4, 4}, {5, 5}, {6, 6}}}, RGBColor[
  0, 1, 0]}, {{{{6, 6}, {7, 7}, {8, 8}}}, RGBColor[
  1, 0, 0]}, {{{{8, 8}, {9, 9}, {10, 10}}}, RGBColor[0, 1, 0]}}

The final block serves to deploy all of the sublists in graphs.

graphs = {};
For[x = 1, x <= Length[graphsData], x++, 
 AppendTo[graphs, 
  ListLinePlot[graphsData[[x, 1]], PlotStyle -> graphsData[[x, 2]]]]]
Show[graphs, PlotRange -> All, GridLines -> Automatic]

And voila: enter image description here

I have yet to pare down the code to a cleaner state, but it works.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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