This should be a simple question. The proc template is used to create the graph output below. All I want to do is change the fill colors of the "COOLING" "REWARMING" and "POST WARMING" blocks at the top. I have played around with the data attribute maps in dataset form as well as using the discreteattrmap in Proc Template.
Can someone point me to how to work these options to get what I need.
The ideal is:
cooling=lightgray
rewarming=lightorange
post-warming=lightgray
proc template;
define statgraph Temperature_overall1 ;
begingraph ;
layout lattice / columns=1 rows=1 ;
cell;
layout lattice / rowweights=(.04 .96);
blockplot x=&x. block=block / datatransparency=.3 valuefitpolicy=shrink labelposition=left
display=(fill label outline values) valuehalign=center ;
layout overlay /yaxisopts=(griddisplay=on labelattrs=(color=black) tickvalueattrs=(color=black)
linearopts=( viewmin=30 viewmax=40 ) display=(Line ticks tickvalues))
xaxisopts=(labelattrs=(color=black) tickvalueattrs=(color=black) display=(Line ticks tickvalues)
linearopts=( viewmin=0 viewmax=100 ))
;
seriesplot x=&x. y=sub_avg / group=zsubjectid lineattrs=(color=black THICKNESS=1 pattern=1) markerattrs=(size=0) DATATRANSPARENCY=.6 ;
referenceline x=cool_ref / lineattrs=(color=black pattern=2);
referenceline x=warm_ref / lineattrs=(color=black pattern=2);
annotate;
endlayout;
endlayout;
endcell;
endlayout;
endgraph;
end;
run;
Hello @GreyJoy,
Use the DATACOLORS= option of the BEGINGRAPH statement:
begingraph / datacolors=(lightgray lightorange lightgray);
Hello @GreyJoy,
Use the DATACOLORS= option of the BEGINGRAPH statement:
begingraph / datacolors=(lightgray lightorange lightgray);
Didn't even know that was an option! Fantastic.
A follow up question - Using the Axistable statement in an innermargin block, i have been unable to get borders around individual cells like you can using the blockplot statement. But with the blockplot, it doesn't seem like there is a way to specifically or dynamically tell it which colors are to be in which blocks.
Outside of your recommendation, which works, is there a way to accomplish either borders around the Axistable cells or explicitly tell the blockplot what colors the cells should be based on the value inside them?
Discrete attribute maps can be used with block plots. Here is an example:
proc template;
define statgraph block;
begingraph / collation=binary;
DiscreteAttrVar attrvar=MYID_AGE var=AGE attrmap="__ATTRMAP__MYID";
DiscreteAttrMap name="__ATTRMAP__MYID" /;
Value "11" / fillattrs=( color=CXFF0000);
Value "12" / fillattrs=( color=CXFFA500);
Value "13" / fillattrs=( color=CXFFFF00);
Value "14" / fillattrs=( color=CX008000);
Value "15" / fillattrs=( color=CX0000FF);
Value "16" / fillattrs=( color=CX800080);
EndDiscreteAttrMap;
layout overlay / yaxisopts=(labelFitPolicy=Split) xaxisopts=(discreteOpts=(tickvaluefitpolicy=SplitRotate));
SeriesPlot X=Name Y=Weight / primary=true display=(markers) LegendLabel="Weight" NAME="SERIES";
InnerMargin / align=bottom;
BlockPlot X=Name Block=MYID_AGE / Display=( Fill Outline Values Label ) valueFitPolicy=split valueHAlign=center valueVAlign=center;
EndInnerMargin;
endlayout;
endgraph;
end;
run;
proc sort data=sashelp.class out=class; by age; run;
proc sgrender data=class template=block; run;
@GreyJoy wrote:
Didn't even know that was an option! Fantastic.
Neither did I until today. 🙂
A follow up question - Using the Axistable statement in an innermargin block, i have been unable to get borders around individual cells like you can using the blockplot statement.
I don't see such an option in the documentation of the AXISTABLE statement.
Outside of your recommendation, which works, is there a way to ... explicitly tell the blockplot what colors the cells should be based on the value inside them?
This is a very good question. I'm not really familiar with the GTL. The block plots that I created in the past were done with the BLOCK statement of PROC SGPLOT. There I used the DATTRMAP= option of the PROC SGPLOT statement to reference a dataset assigning colors to values. I was surprised to see that in GTL the assignment seemed to rely on the order of values. Now, upon your follow-up question I remembered a very valuable trick that I learned earlier this year from this posting by Bruno_SAS: https://communities.sas.com/t5/SAS-Programming/Background-color-of-legend-in-sgplot/m-p/801686/highl... .
So I ran my old block plot program with the TMPLOUT= option (of the PROC SGPLOT statement) added. And -- voilà! -- the resulting .sas file revealed the secret how the value-based color assignment can be done in PROC TEMPLATE: Apparently you need to insert a section like
discreteattrvar attrvar=blockvar var=block attrmap="myattrmap";
discreteattrmap name="myattrmap";
value "COOLING" / fillattrs=(color=lightblue);
value "REWARMING" / fillattrs=(color=lightorange);
value "POST-WARMING" / fillattrs=(color=lightgray);
enddiscreteattrmap;
after the BEGINGRAPH statement, where the names "blockvar" and "myattrmap" are arbitrary user-defined names, and then refer to the first of these names in the BLOCK= option of the BLOCKPLOT statement, i.e.
blockplot x=&x. block=blockvar / ...;
Edit: Oops, the master was faster.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.