BookmarkSubscribeRSS Feed
Manj
Fluorite | Level 6

Hi ,

   Below is the graph im intended to create. As tyou can see it is stacked and grouped and subgrouped with 100% bars.

Im using the following code, but not sure how to achieve the colours and the patterns. Also would like to present the N values at the bottom of each bars. I tried xaxis table ,but it gives all the bar values together at the bottom of each  bars. I pre-calulated the n-values  and tried giving the 'N='  along with the vbar variable by concatenating, but the result was same as that of xolaxistable.

my code below:

 

proc sgpanel data=ip pctlevel=group;
panelby avisit / layout=columnlattice onepanel novarname noborder colheaderpos=top headerattrs=(Size=8) ;
vbar trt01p / group=avalc stat=percent ;
colaxis display=(nolabel) fitpolicy=split splitchar='-' valueattrs=(size=8);
rowaxis grid;
* colaxistable /classdisplay=cluster position=bottom valueattrs=(size=2 color=blue) stat=sum ;
run;
run;

 

Manj_0-1588597904419.png

 

14 REPLIES 14
JeffMeyers
Barite | Level 11
Is your data pre calculated for the bars? I don't see a vbar or vbarparm statement. Can you post your data? I think I can make this pretty quick.
Manj
Fluorite | Level 6

Sorry, The bar are NOT pre-calculated .

My code is 


proc sgpanel data=ip pctlevel=group;
panelby avisit / layout=columnlattice onepanel novarname noborder colheaderpos=top headerattrs=(Size=8) ;
vbar trt01p / group=avalc stat=percent ;
colaxis display=(nolabel) fitpolicy=split splitchar='-' valueattrs=(size=8);
rowaxis grid;
* colaxistable /classdisplay=cluster position=bottom valueattrs=(size=2 color=blue) stat=sum ;
run;

 

JeffMeyers
Barite | Level 11

I did a generic example with the CARS data set since I don't have your data.  Let me know if this helps:

 

proc sort data=sashelp.cars out=cars;
    by origin  drivetrain type;
run;
proc freq data=cars noprint;
    by origin drivetrain;
    table type / out=freq;
run;
proc sql;
    create table counts as
        select origin,drivetrain,catx('`',drivetrain, '(N='||strip(put(sum(count),12.0))||')') as n from freq
        group by origin,drivetrain;
quit;
data plot;
    merge freq counts;
    by origin drivetrain;
    label n = 'Drive Train';
run;


proc sgpanel data=plot;
panelby origin /layout=columnlattice onepanel rows=1 novarname noheaderborder colheaderpos=bottom
headerattrs=(Size=8) uniscale=row ;
colaxis splitchar='`' display=(nolabel) ;
vbarparm category=n response=percent/ group=type fillpattern;
run;

 SGPanel12.png

 

 

 

Manj
Fluorite | Level 6

Thanks for the response, If you can see the sample graph has two colour schemes only-Red and blabk for each panel.

ballardw
Super User

Look up DATTRMAP in the documentation.

That is an option that allows you to control the color/pattern/line/marker appearance for Group variables.

JeffMeyers
Barite | Level 11
Attribute maps frustratingly can't control fill patterns and they only work on group variables I think.
I'm not sure how to control colors by category variable. I can check when I get back to my computer.
ballardw
Super User

You can use the STYLEATTRS statement to set the sequence of patterns and matching colors.

 

Or create a custom style template setting the desired fillpattern for each GraphData element.

 

 

 

 

Manj
Fluorite | Level 6

Thanks . I tried the above code, seems like 'Fillpattern' doesnt work .It shows up WARNING 1-322: Assuming the symbol FILL was misspelled as fillpattern in the log file. Also Are you calculating the 'percent' in the data?

ballardw
Super User

@Manj wrote:

Thanks . I tried the above code, seems like 'Fillpattern' doesnt work .It shows up WARNING 1-322: Assuming the symbol FILL was misspelled as fillpattern in the log file. Also Are you calculating the 'percent' in the data?


Please show the entire proc step along with the with errors. Otherwise we are guessing as to where an issue occurs. Copy the code ande errors from the log and paste into a code box opened on the forum with the </> icon.

 

Also, which version of SAS are you running? Graphics options are one of the fastest changing bits in SAS and if you are running an older version, such as SAS 9.3 then some of these may not be available.

Manj
Fluorite | Level 6

Hi

I use sas version 9.4. 

The code I use is (as you suggested)


proc sgpanel data=ip pctlevel=group;
panelby avisit /layout=columnlattice onepanel rows=1 novarname noheaderborder colheaderpos=bottom headerattrs=(Size=8) uniscale=row ;
colaxis display=(nolabel) fitpolicy=split splitchar='-' ;
vbarparm category=trt response=percent/ group=avalc fillpattern;
run;

 

The log gives the following :

 


13 The SAS System

real time 0.00 seconds
cpu time 0.01 seconds

************************************************************
* Macro name: CU_FIGSTYLE, Macro Version: 1
************************************************************
* CU_FIGSTYLE has been called with the following parameters:
*
CU_FIGSTYLE MACROVERSION 1
*
************************************************************
This Macro does not use any Global Macro Variables
*
************************************************************
NOTE: STYLE 'Idsl' has been saved to: WORK.TEMPLAT
NOTE: PROCEDURE TEMPLATE used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds

NOTE: Writing ODS PDF output to DISK destination "/arenv/arwork/gsk1278863/mid204837/internal_02/output/f_e_stacked_bar_iron1.PDF",
printer "PDF".
NOTE: This SAS session is using a registry in WORK. All changes will be lost at the end of this session.
NOTE: Line generated by the invoked macro "SD_STACKED_BAR_IRON".
439 colheaderpos=bottom headerattrs=(Size=8) uniscale=row ; colaxis display=(nolabel) fitpolicy=split splitchar='-' ;
439 ! vbarparm category=trt response=percent/ group=avalc fillpattern; run; ods pdf close; ods listing;
___________
1
ERROR: Variable PERCENT not found.

WARNING 1-322: Assuming the symbol FILL was misspelled as fillpattern.

NOTE: The SAS System stopped processing this step because of errors.
NOTE: PROCEDURE SGPANEL used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds


ERROR: SAS ended due to errors.
You specified: OPTIONS ERRORABEND;.
ERROR: Errors printed on page 13.

NOTE: SAS Institute Inc., SAS Campus Drive, Cary, NC USA 27513-2414
NOTE: The SAS System used:
real time 1.52 seconds
cpu time 1.28 seconds

 

 

Manj
Fluorite | Level 6

My code (as per your suggestion )

 

 

proc sgpanel data=ip ;
panelby avisit /layout=columnlattice onepanel rows=1 novarname noheaderborder colheaderpos=bottom headerattrs=(Size=8) uniscale=row ;
colaxis display=(nolabel) fitpolicy=split splitchar='-' ;
vbarparm category=trt response=percent/ group=avalc ffillpattern;
run;

 

Log looks as follows:

13 The SAS System

real time 0.00 seconds
cpu time 0.01 seconds

************************************************************
* Macro name: CU_FIGSTYLE, Macro Version: 1
************************************************************
* CU_FIGSTYLE has been called with the following parameters:
*
CU_FIGSTYLE MACROVERSION 1
*
************************************************************
This Macro does not use any Global Macro Variables
*
************************************************************
NOTE: STYLE 'Idsl' has been saved to: WORK.TEMPLAT
NOTE: PROCEDURE TEMPLATE used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds

NOTE: Writing ODS PDF output to DISK destination "/arenv/arwork/gsk1278863/mid204837/internal_02/output/f_e_stacked_bar_iron1.PDF",
printer "PDF".
NOTE: This SAS session is using a registry in WORK. All changes will be lost at the end of this session.
NOTE: Line generated by the invoked macro "SD_STACKED_BAR_IRON".
439 colheaderpos=bottom headerattrs=(Size=8) uniscale=row ; colaxis display=(nolabel) fitpolicy=split splitchar='-' ;
439 ! vbarparm category=trt response=percent/ group=avalc fillpattern; run; ods pdf close; ods listing;
___________
1
ERROR: Variable PERCENT not found.

WARNING 1-322: Assuming the symbol FILL was misspelled as fillpattern.

NOTE: The SAS System stopped processing this step because of errors.
NOTE: PROCEDURE SGPANEL used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds

 

ballardw
Super User

Again it helps to post the code using the code box opened with the forum's </>.

This bit of the code:

! vbarparm category=trt response=percent/ group=avalc fillpattern; run; ods pdf close; ods listing;
___________
1
ERROR: Variable PERCENT not found.

The Response variable to use VBARPARM has to be in the data. A Vbar or Vbarbasic plot can request a statistic but Vbarparm requires presummarized data and you provide the variable names with the values.

From documentation:

VBARPARM CATEGORY=category-variable RESPONSE=numeric-variable </option(s)>;

IF fillpattern was acceptable then you would have to provide a value, and in this position it would set the same pattern for all items. I would suggest removing that from the VBARPARM statement.

 

Your code says:

NOTE: STYLE 'Idsl' has been saved to: WORK.TEMPLAT

but does not show anything related to the style.

 

 

 

Manj
Fluorite | Level 6

Hi,

 The syle IDSL is internal to the organisation. plz leave that aside. The methoeds I tried are below:

 

Method 1 :

========

pattern1 v=l1 c=black;
pattern2 v=x1 c=black;
pattern3 v=r1 c=black;
pattern4 v=l2 c=black;
pattern5 v=x2 c=black;
pattern6 v=r2 c=black;


axis1 label=none order=('Baseline' 'Day 1 - < Week 12' 'Week 12 - < Week 24' 'Week 24 - < Week 36' 'Week 36 - < Week 48' 'Week 48 - < Week 52') offset=(2,2) ;
axis3 label=none minor=none style=0 offset=(0,0) ;

legend1 shape=bar(.15in,.15in) offset=(0,-3);
goptions device=PDF;

proc gchart data=ip2;
   vbar trt / discrete subgroup=avalc group=avisit nozeros type=percent g100 noframe gaxis=axis1 r   axis=axis3 patternid=subgroup gspace=4 space=.5 legend=legend1;
run;

 

 The issue here is it doesnt give the 100% bars and gives only one colour (i would need two colours for group and  6 pattern - for subgroup).

 

Method 2:

========

proc sgpanel data=ip2 pctlevel=group;
   panelby avisit /layout=columnlattice onepanel rows=1 novarname noheaderborder noborder      colheaderpos=bottom headerattrs=(Size=8) uniscale=row ;
colaxis display=(nolabel) fitpolicy=split splitchar='-' ;
vbar trt / group=avalc stat=percent barwidth=.95 clusterwidth=1;
*vbarparm category=trt response=percent/group=avalc fill;
keylegend /title='' ;
run;

 

Vbarparm was not working fine. This above method gives everything other than the pattern(6 patterns for the subgroups) and the colours (two colurs for two different groups).

 

 

 

RichardDeVen
Barite | Level 11

In this answer the PANELBY is TIMEFRAME, VBAR is TREATMENT, and  / GROUP= is THERAPY

 

The core issue is that /GROUP THERAPY values are driving the patterning.  These values and their patterns appear in the legend. The categorical data set has the fully expected situation that THERAPY values encountered in one TREATMENT will be the same as encountered in a different TREATMENT.  This means the THERAPY based patterning can not accommodate the TREATMENT it is under and thus can not drive color differentiation.

 

Let's simulate some data so others can play along.  The therapy value is coded 0 to 7 and the timeframe is code 0 to 3:

 

 

proc format; 
  value timeframe
  0 = 'Baseline iron use'
  1 = 'Day 1 : Week 12'
  2 = 'Week 12 : Week 24'
  3 = 'Week 24 : Week 36'
  ;

  value therapy
  0 = 'None'
  1 = 'Only IV' 
  2 = 'Only Oral'
  3 = 'Only Other'
  4 = 'Both IV + Oral'
  5 = 'Both IV + Other'
  6 = 'Both Oral + Other'
  7 = 'All IV + Oral + Other'
  ;
run;

data have(keep=patid--timeframe);
  top = 400;
  call streaminit(1234);
  length patid 8 treatment $8 therapy 8 timeframe 8 ;
  do treatment = 'Dapro', 'rhEPO';
    * 400 Dapro, 600 rhEPO;
    do i = 1 to top;
      patid + 1;

      p = rand('uniform', 100);
      select;
        when (p < 40.0) therapy = 0;
        when (p < 85.0) therapy = 1;
        when (p < 92.0) therapy = 2;
        when (p < 93.5) therapy = 3;
        when (p < 95.0) therapy = 4;
        when (p < 96.5) therapy = 5;
        when (p < 98.0) therapy = 6;
        otherwise therapy = 7;
      end;

      do timeframe = 0 to 3;
        * simulate a 3% patient drop out at any timeframe;
        if rand('uniform') < 0.03 then leave;

        * simulate an entire bar segment with no patients;
        if treatment = 'rhEPO' and timeframe = 3 and therapy = 1 then leave;
        output;
      end;
    end;
    top + 200;
  end;
  format 
    timeframe timeframe.
    therapy therapy.
  ;
run;

 

 

Take a look at the simplest first try that uses STYLE=JOURNAL2 for its grayscale theme:

 

 

ods html path='.' file='vbar.html' style=Journal2;

proc sgpanel data=have pctlevel=group;
  title 'Simple Starter Plot';
  panelby timeframe / 
    layout=columnlattice 
    onepanel 
  ;

  vbar treatment / 
    group=therapy
    stat=percent
  ;
run;

 

 

 

VBAR Starter.png

 

The attached code shows the steps and some intermediate plots demonstrating the transition to a final plot with desired features.  The pre plot processing includes:

  • Creating a custom template named StackedVbarGroupCrossVar based on Journal2
    • The first eight GraphData styles elements (for the 8 therapies) specify the cross hatch patterns to use
    • Another eight GraphData style elements specify the same hatching with ContrastColor=LIGHTRED
  • Creating a custom format THERAPY_CROSS_TREATMENT to deal with a transformed value of THERAPY that accounts for TREATMENT
  • Computing the counts for each TREATMENT & TIMEFRAME combination
  • Create a PLOT data set that has
    • New column BAR_COUNT that contain the computed counts
    • New column THERAPY_CROSS_TREATMENT that segregates therapy according to TREATMENT (Dapro nochange, rhEPO therapy code+10)
    • New column TREATMENT_WITH_COUNT that has "/(N=<combination-count>)" concatenated to TREATMENT

The tweaked data now has everything needed tricking out the plot into a final presentation created using the custom template StackedVbarGroupCrossVar:

  • Compute a quoted list of the rhEPO specific THERAPY_CROSS_TREATMENT formatted values so they can be EXCLUDEd from the KEYLEGEND
  • Add PANELBY options:
    • novarname
      noborder
      colheaderpos=bottom
      headerbackcolor=white
      noheaderborder
      uniscale=row  (not having uniscale col will let proc remove 'nobar' ticks)
  • Change the VBAR statement to use tweaked values
    • vbar treatment_with_count /
        group=therapy_cross_treatment ...
  • Update the KEYLEGEND to exclude the segregating group values beyond the first eight
    • keylegend / ... exclude=(&keyexcludes)
  • Add a rowaxis to display 10% intervals
    • rowaxis values = (0 to 1 by 0.1) ... ;
  • Add a colaxis with splitalways so the combination count (the bar total counts) appears below the TREATMENT
proc sgpanel data=plot pctlevel=group;
  title 'Presentation Plot Final';
  panelby timeframe / 
    layout=columnlattice 
    onepanel 
    novarname
    noborder
    colheaderpos=bottom
    headerbackcolor=white
    noheaderborder
    uniscale=row
  ;

  vbar treatment_with_count / 
    group=therapy_cross_treatment
    stat=percent
  ;

  label therapy_cross_treatment = 'Iron therapy';

  keylegend / 
    across=4 
    outerpad=14px 
    noborder
    exclude=(&keyexcludes)
  ;

  rowaxis 
    values = (0 to 1 by 0.1)
    display=(noline noticks)
    grid
  ;

  colaxis
    display=(nolabel)
    fitpolicy=splitalways
    splitchar='/'
    valueattrs=(size=8pt)
  ;
run;

VBAR Final.png

 

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

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

View all other training opportunities.

Discussion stats
  • 14 replies
  • 4776 views
  • 4 likes
  • 4 in conversation