BookmarkSubscribeRSS Feed
Pyrite | Level 9

Hi everyone,

I am trying to generate a series of paneled spaghetti plots. There will be three panels, one for each of certain allocated treatments. Each panel will consist of two overlaid spaghetti plots; one showing observed trajectories of some metric, the other showing expected trajectories determined by a model. The purpose being to compare the observed and expected trajectories under each treatment allocation (the hypothesis being that the individuals in a certain treatment will have higher values relative to the expectation than the other groups. The details aren't important beyond this). This is a peculiarly difficult figure to create, however. The issue being that it requires two calls to the SERIESPLOT statement, as opposed to one call to the SERIESPLOT statement with the LINECOLORGROUP option specified. My code is as follows (unfortunately, at the moment I don't have an example dataset available. If nobody sees an obvious solution based on my code, I will work on creating example data to let people fiddle with the code more):

VISNO is a variable indicating time, PATID is the patient ID, and OBSERVED and EXPECTED are the two (continuous) outcome variables that will fall on the Y-axis of the plot. DUMMY1 and DUMMY2 are random variables I created for the discreteattrmap; they are simply character variables with the same value for every individual.

Note that OBSERVED and EXPECTED are two different columns in the dataset, with an equal number of observations. Thus leading to my problem. All of the examples I can find using the LINECOLORGROUP option in seriesplot are based on values in a single variable (column) with a different (categorical) variable used to define different levels on which to assign colors. That isn't the case, here, because I am actually overlaying two separate spaghetti plots. I want all of the lines for each spaghetti plot to be of the same color; the comparison of interest is the observed vs. expected; however, it is of interest to see the trajectories for every single individual, as opposed to aggregating them to a mean.


    define statgraph spaghetti;


          entrytitle "Observed and Expected Trajectories";

          discreteattrmap name="Observed" / ;

              value "Observed" / lineattrs=(color=black) ;

          enddiscreteattrmap ;

          discreteattrmap name="Expected" / ;

              value "Expected" / lineattrs=(color=red) ;

          enddiscreteattrmap ;

          discreteattrvar attrvar=obvar var=dummy1 attrmap="Observed" ;

          discreteattrvar attrvar=exvar var=dummy2 attrmap="Expected" ;

          layout datapanel classvars=(treatment) / rows=1 columns=3 columnaxisopts=( linearopts=(integer=true) ) headerlabeldisplay=value;

              sidebar / align=bottom;

                    discretelegend "obs" "exps" / displayclipped=true type=linecolor border=false;


              layout prototype;

                    seriesplot x=visno y=observed / group=patid linecolorgroup=obvar name="obs";

                    seriesplot x=visno y=expected / group=patid linecolorgroup=exvar name="exps";






PROC SGRENDER data=exp_spaghetti template=spaghetti;


So you see what I am trying to do is color all of the lines from the observed seriesplot black, and all of the lines from the expected seriesplot red. However, as you can see from the attached image (output using this code), it clearly isn't working. It is assigning the same blue color to every line (and also adjusting the line patterns for reasons I can't discern). Now, I can probably get around this by creating a new dataset and stacking all of the observed and expected values into a single column and creating a dummy variable to distinguish them, but that seems like a clunky workaround.

Why, in this case, is the discreteattrvar statement not properly assigning the colors through linecolorgroup? There are no errors or warnings in the log whatsoever. Further, if I try adding, for example, "lineattrs=(color=black)" to the SERIESPLOT statements in the above code, it has no effect on the color of the final plot.

Does anybody know what the problem here is?

(EDIT: It keeps telling me my attached image is too large. So here is a link to it:


You are not required to specify an attrmap in the this case. Even when you are using a group, you can force the color of the lines to be constant, like so:


seriesplot x=visno y=observed / group=patid lineattrs=(color=black);

seriesplot x=visno y=expected / group=patid lineattrs=(color=red);


Let me know if this solves your issue, or if I have misunderstood the problem 🙂




Pyrite | Level 9

Thank you for the response. In all honesty, it's been so long since I posted this question I don't remember why I was trying to use discreteattrmap. I'll have to go back through my server and find the project this was for and check, but just from looking at the code I don't see why your solution wouldn't work ...



Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.

If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website. 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Get the $99 certification deal.jpg



Back in the Classroom!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 2 replies
  • 2 in conversation