0

Following data has two groups Group 1 and Group 2. Each group has multiple subjects.

data sgplot_CPA;
   input trt_group$ time$ subject$ 11. results;
   datalines;
    Group-1 1 203-070-001 20
    Group-1 3 203-070-001 30
    Group-1 7 203-070-001 35
    Group-1 10 203-070-001 50
    Group-1 14 203-070-001 40
    Group-1 21 203-070-001 25
    Group-1 28 203-070-001 40
    Group-1 US 203-070-001 30
    Group-1 1 203-070-003 25
    Group-1 3 203-070-003 35
    Group-1 7 203-070-003 30
    Group-1 10 203-070-003 40
    Group-1 14 203-070-003 50
    Group-1 21 203-070-003 21
    Group-1 28 203-070-003 24
    Group-1 US 203-070-003 31
    Group-1 1 203-070-005 32
    Group-1 3 203-070-005 22
    Group-1 7 203-070-005 30
    Group-1 10 203-070-005 56
    Group-1 14 203-070-005 28
    Group-1 21 203-070-005 35
    Group-1 28 203-070-005 29
    Group-1 US 203-070-005 41
    Group-2 1 203-070-007 15
    Group-2 3 203-070-007 45
    Group-2 7 203-070-007 23
    Group-2 10 203-070-007 48
    Group-2 14 203-070-007 26
    Group-2 21 203-070-007 17
    Group-2 28 203-070-007 35
    Group-2 US 203-070-007 11
    Group-2 1 203-070-008 27
    Group-2 3 203-070-008 40
    Group-2 7 203-070-008 25
    Group-2 10 203-070-008 30
    Group-2 14 203-070-008 40
    Group-2 21 203-070-008 19
    Group-2 28 203-070-008 28
    Group-2 US 203-070-008 39
;
run;

I would like to add two legend in the Spaghettin plot, one for Treatment group (trt_group) and one for subject. Say for Group-1, All line will be purple color, within each group separate marker for each subject to identify the subject trend.

Here is code I have tried,

proc sgplot data=sgplot_CPA;
styleattrs datacontrastcolors=(purple green orange)
             datasymbols=(squarefilled trianglefilled circlefilled StarFilled TriangleDownFilled )
             datalinepatterns=(Solid Solid Solid ShortDash  ShortDash MediumDash LongDash MediumDashShortDash);           
/*   title 'Study Results by Treatment Group';*/
   series x=time y=results / group=subject grouplc=trt_group name='grouping' groupdisplay=cluster clusterwidth=0.25 Markers MARKERATTRS = (color = black) ;
   scatter x =time y = results / group = subject name = 'subjects' groupdisplay=cluster clusterwidth=0.25 markerattrs=(color = black );
   keylegend 'grouping' / type=linecolor sortorder = ASCENDING Position = TopLeft title="Treatment";
   keylegend 'subjects' / type =marker sortorder = ASCENDING Position = Bottom title="Subject";
   xaxis label="Visit";                                                                                       
   yaxis label="Result Score"; 
   footnote J=L "US=Unscheduled";
run;

Here is the output

enter image description here

How can I change the highlighted legend to different marker style? For example, 203-070-001 should have star symbol with purple color, 203-070-003 should have square with purple color, and 203-070-005 should have triangle with purple color and similar for Group 2. Any help is appreciated.

Uddin
  • 754
  • 5
  • 18
  • Discrete Attribute Maps https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/grstatproc/p18q268a3zxcl3n11lnnnq4cme8r.htm – Reeza Aug 25 '22 at 19:39

1 Answers1

1

You will need to use data attribute maps. I find that the SAS documentation on this topic is somewhat weak and too widely dispersed amongst different pages and simplistic examples.

Example:

The data attribute maps demonstrated presumes a subject has only single treatment.

/* 
 * derive attribute maps SERIES_ATTR and MARKERS_ATTR
 * based on actual data being plotted
 */

data attribute_map;
  length id $30 value $50;

  set sgplot_cpa;
  by trt_group subject;

  * zero-based arrays for easy modulus indexing that will loop through each array;

  array colors [0:2] $32 _temporary_ 
    ('purple' 'green' 'orange');
  array markers[0:4] $32 _temporary_ 
    ('starfilled' 'squarefilled' 'trianglefilled' 'circlefilled' 'diamondfilled');

  retain counter1 -1;
  
  if first.trt_group then do;
    * wanted: series attributes that vary by treatment;

    counter1 ++ 1;  * increase modulus index for treatment;
    counter2 = -1;  * reset modulus index for subject;

    id = 'SERIES_ATTR';
    value = trt_group;
    linecolor = colors[mod(counter1,dim(colors))];  * apply modulus index;
    output;

    call missing (id, value, linecolor);
  end;

  if first.subject;

  * wanted: scatter attribute that vary by subject, resetting for each treatment;

  counter2 ++ 1; * increase modulus index for subject within treatment;

  id = 'MARKERS_ATTR';
  value = subject;

  markercolor = colors[mod(counter1,dim(colors))];
  markersymbol = markers[mod(counter2,dim(markers))];

  output;

  keep id value markercolor markersymbol linecolor;
run;
proc sort;
  by id value;
run;


ods html file='report.html';

* series and scatter are used because two different keylegends are wanted;

proc sgplot data=sgplot_CPA dattrmap=attribute_map;
   series x=time y=results 
    / name='treatments' 
      group=subject 
      groupdisplay=cluster 
      clusterwidth=0.25 
      grouplc=trt_group 
      lcattrid=SERIES_ATTR
   ;
   scatter x=time y=results
    / name = 'subjects'
      group = subject
      attrid = MARKERS_ATTR
      groupdisplay=cluster
      clusterwidth=0.25
   ;

   keylegend 'treatments' / type=linecolor sortorder=ascending position=TopLeft title="Treatment";
   keylegend 'subjects'   / type=marker    sortorder=ascending position=Bottom  title="Subject";
   xaxis label="Visit";                                                                                       
   yaxis label="Result Score"; 
   footnote J=L "US=Unscheduled";
run;

ods html close;

enter image description here

Richard
  • 25,390
  • 3
  • 25
  • 38
  • Note: As the number of subjects to be plotted increases it is more useful to use a boxplot of subject results at each visit. You might also want to look into using SGPANEL and have a separate panel for each treatment. – Richard Aug 29 '22 at 13:59
  • The code is not working for more than two groups. I made changed the array lines to `array colors [0:3] $32 _temporary_` instead of `array colors [0:2] $32 _temporary_` – Uddin Aug 29 '22 at 15:52