Showing markers on a series chart using the GTL - sas

I'm trying to get markers to show up on my chart using the Graphics Template Language. I've tried adding the marker definitions to the style, to the seriesplot statement within a markerattrs= option statement, and also using discreteattrmaps for the chart group. I can't seem to get any of these approaches working.
Style definition:
proc template;
define style excel;
parent=styles.htmlblue;
class graph / attrpriority='none';
style graphdata1 / contrastColor=#416FA6;
style graphdata2 / contrastColor=#A8423F;
style graphdata3 / contrastColor=#86A44A;
style graphdata4 / contrastColor=#8064A2;
style graphdata5 / contrastColor=#DA8137;
style graphdata6 / contrastColor=#D7E4BD;
style graphdata7 / contrastColor=#FCD5B5;
style graphdata8 / contrastColor=#8EA5CB;
style graphdata9 / contrastColor=#E6B9B8;
style graphdata10 / contrastColor=#CCC1DA;
end;
run;
Template for the chart:
proc template;
define statgraph excel_series_trended;
dynamic _date _class _metric _title;
begingraph;
entrytitle halign=center _title;
discreteattrmap name="symbols" / ignorecase=true ;
value "IBM" / markerattrs=(color=blue symbol=diamondfilled) ;
value other / markerattrs=(color=red symbol=circlefilled) ;
enddiscreteattrmap ;
discreteattrvar attrvar=groupmarkers var=stock attrmap="symbols" ;
layout lattice / rowdatarange=data columndatarange=data rowgutter=0 columngutter=0;
layout overlay / walldisplay=(fill)
yaxisopts=( griddisplay=on gridattrs=(pattern=2 color=Cx999999) linearopts=(viewmin=0) )
xaxisopts=( type=discrete );
seriesplot x=_date y=_metric / group=_class markercolorgroup=_class name='series' groupdisplay=overlay connectorder=xaxis lineattrs=(pattern=solid thickness=3);
endlayout;
sidebar / align=bottom spacefill=false;
discretelegend 'series' / opaque=true border=false halign=center valign=center displayclipped=true order=rowmajor;
endsidebar;
endlayout;
endgraph;
end;
run;
Render the chart using the sashelp.stocks dataset:
ods html style=excel;
ods graphics / antialias=on antialiasmax=999999;
proc sgrender data=sashelp.stocks template=excel_series_trended;
where date between '01jan2005'd and '01jun2005'd;
dynamic _date="date" _metric="high" _class="stock";
run;

You need to do two things, presumably.
First, add display=(markers) to the seriesplot statement; that enables markers.
Second, add markersymbolgroup=groupmarkers to that same statement to enable the discrete attribute map to be used for markers, and change markercolorgroup to the same value. You cannot use a dynamic variable to define these, and shouldn't - you should use the discreteattrvar value.
Full code:
proc template;
define statgraph excel_series_trended;
dynamic _date _class _metric _title;
begingraph;
entrytitle halign=center _title;
discreteattrmap name="symbols" / ignorecase=true ;
value "IBM" / markerattrs=(color=blue symbol=diamondfilled) ;
value other / markerattrs=(color=red symbol=circlefilled) ;
enddiscreteattrmap ;
discreteattrvar attrvar=groupmarkers var=stock attrmap="symbols" ;
layout lattice / rowdatarange=data columndatarange=data rowgutter=0 columngutter=0;
layout overlay / walldisplay=(fill)
yaxisopts=( griddisplay=on gridattrs=(pattern=2 color=Cx999999) linearopts=(viewmin=0) )
xaxisopts=( type=discrete );
seriesplot x=_date y=_metric / group=_class name='series'
markersymbolgroup=groupmarkers markercolorgroup=groupmarkers
groupdisplay=overlay connectorder=xaxis lineattrs=(pattern=solid thickness=3)
display=(markers);
endlayout;
sidebar / align=bottom spacefill=false;
discretelegend 'series' / opaque=true border=false halign=center valign=center displayclipped=true order=rowmajor;
endsidebar;
endlayout;
endgraph;
end;
run;

Although I've marked Joe's answer as accepted I ended up choosing a slightly different solution that was easier to maintain in my final project.
The key part of the syntax I was missing was the display=(markers) option on seriesplot (as Joe pointed out). Once that was added, I was able to control the marker symbol simply by specifying it in the style:
proc template;
define style excel;
parent=styles.htmlblue;
class graph / attrpriority='none';
style graphdata1 / contrastColor=#416FA6 markersymbol='circlefilled';
style graphdata2 / contrastColor=#A8423F markersymbol='circlefilled';
style graphdata3 / contrastColor=#86A44A markersymbol='circlefilled';
end;
run;
Unfortunately the style does not support the markersize= option (despite what the documentation says). For that I ended up adding the markerattrs=(size=_markersize) option to the seriesplot statement. I made _markersize a dynamic value with a default of 0px, (ie. don't show markers). Now the template allows me to easily change the symbol, and or the size of the markers:
proc template;
define statgraph excel_series_trended;
dynamic _date _class _metric _title _markersize=0px;
begingraph;
entrytitle halign=center _title;
layout lattice / rowdatarange=data columndatarange=data rowgutter=0 columngutter=0;
layout overlay / walldisplay=(fill)
yaxisopts=( griddisplay=on gridattrs=(pattern=2 color=Cx999999) linearopts=(viewmin=0) )
xaxisopts=( type=discrete );
seriesplot x=_date y=_metric / display=(markers) group=_class name='series' groupdisplay=overlay connectorder=xaxis
lineattrs=(pattern=solid thickness=3)
markerattrs=(size=_markersize)
;
endlayout;
sidebar / align=bottom spacefill=false;
discretelegend 'series' / opaque=true border=false halign=center valign=center displayclipped=true order=rowmajor;
endsidebar;
endlayout;
endgraph;
end;
run;

Related

SAS PROC GPLOT ERROR: The ORDER= entry is not a legend value

My problem is with the order option of legend statement in Proc GPLOT in SAS.
I can't get my graph to show only selected variables in the legend.
I have tried changing the names of the variables and their labels, and I know a similar procedure was working perfectly fine on other data.
ods html file="..." gpath="...";
ods graphics on;
goptions reset=all hsize=24cm vsize=15cm;
Title;
axis1 label = none
order = (300000 to 1000000 by 100000)
value = (angle=0 height=1.5);
axis2 label = none
/* order = (1 to 12 by 1) */
offset = (0.4 cm, 0.4 cm)
minor=none
value = (angle=0 height=1.5
'sty' 'lut' 'mar' 'kwi' 'maj' 'cze' 'lip' 'sie' 'wrz' 'paź' 'lis' 'gru');
symbol1 color="Medium Vivid Red" interpol=spline line=1 value=dot height=1.2 width=1;
symbol2 color="Medium Vivid Blue" interpol=spline line=1 value=dot height=1.2 width=1;
symbol3 color="Medium Vivid Red" interpol=spline line=3 value=none height=1.2 width=1;
symbol4 color="Medium Vivid Blue" interpol=spline line=2 value=none height=1.2 width=1;
symbol5 color="Medium Vivid Red" interpol=spline line=3 value=none height=1.2 width=1;
symbol6 color="Medium Vivid Blue" interpol=spline line=2 value=none height=1.2 width=1;
legend1 order=('ExpPred' 'ArimaPred' 'ExpU95' 'ArimaU95') label=none value = (justify= left
'F' 'S' 'T' 'G') frame;
/* legend1 order=('ExpPred' 'ArimaPred' 'ExpU95' 'ArimaU95') label=none shape=symbol(4,1.25) value = (justify= left
'Prognoza modelem Wintersa' 'Prognoza modelem SARIMA' 'Przedziały ufności (95%) - Model Wintersa'
'Przedziały ufności (95%) - Model SARIMA'); */
proc gplot data = ltz.ltz_Comp2019;
plot (ExpPred ArimaPred ExpU95 ArimaU95 ExpL95 ArimaL95)*data / vaxis=axis1 haxis=axis2 legend=legend1 overlay;
run;
quit;
ods graphics off;
ods html close;
I expect to get a graph with only the values selected in the order statement in the legend, but I get the error:
ERROR: The ORDER= entry "ExpPred" is not a legend value.
The same error is given with other variables or if changed the name of the variable.
Added photo of dataset:
https://i.stack.imgur.com/ULfPp.png

sgpanel vbar distinguist with fill-pattern within groups of the same colour

i'm using SAS 9.4 and created a nice bar-chart with sgpanel like this
enter image description here
The code is as follows:
proc sgpanel data=transp_5;
panelby position / layout=columnlattice onepanel
colheaderpos=bottom rows=2 novarname noborder;
styleattrs datacolours=(CXbe0a6e CXbe0a6e
CXe17d00 CXe17d00
CXbcc121 CXbcc121
CX3caf7f CX3caf7f
CX0077ad CX0077ad)
DATACONTRASTCOLORS=(nocolour);
format position order.;
format crop_type concatf.;
vbar crop_type / group=crop_type response=col1 stat=sum nostatlabel
barwidth=1 groupdisplay=cluster CLUSTERWIDTH= 1;
colaxis display=none;
rowaxis grid labelattrs =(size=12) valueattrs=(size=12)
label="probability" ;
keylegend / valueattrs=(size=10) titleattrs=(size=10) AUTOITEMSIZE
title="crop group" down=2;
where time in ("Feb01", "Jul02", "Aug01", "Sep01" ," Okt02" ,
"Nov01");
run;
Wat i want now, is to distinguish between the attributes "Ps" and "Pfw" for the crops (e.g. corn maize with the SAME colour) by using a fill pattern like dashed or something else.
I found the FILLPATTERNATTRS= options which should work with sgpanelm but it doesn't work so far.
How can i combine fill colours and fill patterns with sgpanel in SAS 9.4?
Thanks,
Sandra
I use SAS 9.4 and updated to M5 in order to use the fillpatterms, but it didn't work. BUT: i solved it, yeah! See the result here: enter image description here
i used a style template and modified it a little as follows
proc template;
define style Styles.meins;
parent = styles.Journal3;
style GraphData1 from GraphData1 /
fillpattern = "solid";
style GraphData2 from GraphData2 /
fillpattern = "L1";
style GraphData3 from GraphData3 /
fillpattern = "solid";
style GraphData4 from GraphData4 /
fillpattern = "L1";
style GraphData5 from GraphData5 /
fillpattern = "solid";
style GraphData6 from GraphData6 /
fillpattern = "L1";
style GraphData7 from GraphData7 /
fillpattern = "solid";
style GraphData8 from GraphData8 /
fillpattern = "L1";
style GraphData9 from GraphData9 /
fillpattern = "solid";
style GraphData10 from GraphData10 /
fillpattern = "L1";
style GraphData11 from GraphData11 /
fillpattern = "solid" ;
style GraphData12 from GraphData12 /
fillpattern = "L1" ;
style GraphData13 from GraphData13 /
fillpattern = "solid";
end;
run;
ods graphics on;
ods html path ='datasave_path'
image_dpi=500
style=meins; quit;
proc sgpanel data=zusammen;
panelby position/ layout=columnlattice onepanel
colheaderpos=top novarname noborder spacing=1;
styleattrs datacolors=(CXbe0a6e CXbe0a6e
CXe13f0d CXe13f0d
CXe17d00 CXe17d00
CXbcc121 CXbcc121
CX3caf7f CX3caf7f
CX0077ad CX0077ad
CXB2B2B2)
DATACONTRASTCOLORS=(black);
format position order.;
format crop_type concatf_a.;
vbar crop_type / group=crop_type response=col1 stat=sum nostatlabel
barwidth=1 groupdisplay=cluster
CLUSTERWIDTH=1;
colaxis display=none;
rowaxis grid labelattrs =(size=12) valueattrs=(size=12)
label="probability" GRID VALUES = (0 TO 1 BY 0.1);
keylegend / valueattrs=(size=10) titleattrs=(size=0) AUTOITEMSIZE
title="" down=4 noborder;
where time in ("Feb01", "Feb02" , "Mar01" , "Mar02" , "Apr01" );
run;
I didn't trie the attribute map, but this would have been the next step if the style template wouldn't have been working.
Thanks,
Sandra

min/max function work-around in SAS

Essentially, what I would like to do is use the min/max function while altering a table. I am altering a table, adding a column, and then having that column set to a combination of a min/max function. In SAS, however, you can't use summary functions. Is there a way to go around this?
There are many more inputs but for the sake of clarity, a condensed version is below! Thanks!
%let variable = 42
alter table X add Z float;
update X
set C = min(max(0,500 - %sysevalf(variable)),0);
First, let's remove the %sysevalf(), they are not needed and format for readability
alter table claims.simulation add Paid_Claims_NoISL float;
update claims.simulation
set Paid_Claims_NoISL
= min(
max(0
, Allowed_Claims -&OOPM
, min(Allowed_Claims
,&Min_Paid+ max(Allowed_Claims - &Deductible * &COINS
,0
)
)
, &Ind_Cap_Claim
)
);
Notice that the first min() only has 1 argument. That is causing your ERROR. SAS thinks that because it only has 1 input, you want to summarize a column, which is not allowed in an update.
Just take that out and it should work:
alter table claims.simulation add Paid_Claims_NoISL float;
update claims.simulation
set Paid_Claims_NoISL
= max(0
, Allowed_Claims -&OOPM
, min(Allowed_Claims
,&Min_Paid+ max(Allowed_Claims - &Deductible * &COINS
,0
)
)
, &Ind_Cap_Claim
);
To reference the value of a macro variable you need to use &.
%let mvar = 42;
proc sql;
update X set C = min(max(0,500 - &mvar),0);
quit;
Note there is no need to use the macro function %SYSEVALF() since SAS can more easily handle the case when the value &mvar is an expression than the macro processor can.
%let mvar = 500 - 42;
proc sql;
update X set C = min(max(0,&mvar),0);
quit;

add inset graph in sas?

I'm wondering if there's a way to add an inset graph in another graph in SAS. I see quite a bit of stuff about adding text insets into a figure, but nothing about a graph. I am making scatterplots with, for example, leaf mass on the x-axis, and leaf area on the y. The slope of the line tells me the ratio of these two quantities, which is specific leaf area. This is also important, so I want to be able to show that, as well. But since its not new information (relative to the scatterplots), I don't want to make another figure since it will basically show the same thing, just in different ways. But if I had it as an inset, that would be okay.
I use SAS 9.4 at school and SAS university edition at home. Here's the code I have for the scatterplot:
proc template; define statgraph Graph;
dynamic _MASS_PER_LEAF _SA_PER_LEAF _GROUP _LT_MASS_PER_LEAF _LT_SA_PER_LEAF _GROUP2;
begingraph / designwidth=500 designheight=819 attrpriority=none DataSymbols=(circle x circle x circle x) DataContrastColors=(CX0000FF CX0000FF CXCC0033 CXCC0033 CX639A21 CX639A21)
DataLinePatterns=(1 2 1 2 1 2);
legendItem type=marker name='Beech' / label = 'Beech' markerattrs=(color=CX0000FF symbol=circlefilled) ;
legendItem type=marker name='Red Maple' / label = 'Red Maple' markerattrs=(color=CXCC0033 symbol=circlefilled) ;
legendItem type=marker name='Sugar Maple' / label = 'Sugar Maple' markerattrs=(color=CX639A21 symbol=circlefilled) ;
legendItem type=marker name='Calcium' / label = 'Calcium' markerattrs=(color=black symbol=circle) ;
legendItem type=marker name='Control' / label = 'Control' markerattrs=(color=black symbol=x) ;
layout lattice / rowdatarange=data columndatarange=union rows=2 rowgutter=10 columngutter=10 rowweights=(1.0 1.0);
layout overlay / yaxisopts=( label=('Average surface area per leaf (cm^2)'));
scatterplot x=_MASS_PER_LEAF y=_SA_PER_LEAF / group=_GROUP name='scatter' markerattrs=(size=11 weight=bold );
regressionplot x = mass_per_leaf y = sa_per_leaf / group = group;
entry halign=left 'Green leaves' / valign=top;
endlayout;
layout overlay / yaxisopts=( label=('Averge surface area per leaf (cm^2)'));
scatterplot x=_LT_MASS_PER_LEAF y=_LT_SA_PER_LEAF / group=_GROUP2
name='scatter2' markerattrs=(size=11 weight=bold );
regressionplot x = mass_per_leaf y = sa_per_leaf / group = group;
entry halign=left 'Senesced leaves' / valign=top;
discretelegend 'Beech' 'Red Maple' 'Sugar Maple' 'Calcium' 'Control' /
opaque=false
border=true
halign=right
valign=bottom
displayclipped=true
down=3
order=columnmajor
location=inside;
endlayout;
columnaxes;
columnaxis / label=('Average mass per leaf (g)');
endcolumnaxes;
endlayout;
endgraph;
end;
run;
proc sgrender data=WORK.CALCIUM template=Graph;
dynamic _MASS_PER_LEAF="'MASS_PER_LEAF'n" _SA_PER_LEAF="'SA_PER_LEAF'n" _GROUP="GROUP" _LT_MASS_PER_LEAF="'LT_MASS_PER_LEAF'n" _LT_SA_PER_LEAF="'LT_SA_PER_LEAF'n" _GROUP2="GROUP";
run;
Thank you for any help!

SAS Proc Report and Proc Template

My aim is to produce a report as shown below:
I almost got it right with ods style 'Journal'. Here's my code and a screenshot of the output that I got.
ods rtf file="C:\Documents and Settings\trainee1\Desktop\table.rtf" bodytitle style=Journal;
options nodate nonumber ls=250 ps=300;
title1 justify =left height =1 font= 'Courier New' c=black "XXXX Pharmaceuticals Corp" justify = right "Draft";
title2 justify =left height =1 font= 'Courier New' c=black "Protocol 5326-02" j=right 'Page !{thispage} of !{lastpage}';
title3 justify=center font="Courier new" height=1 "Listing 14.1.3" ;
title4 justify=center font="Courier new" height=1 "Subject Demographic and Baseline Characteristics by Dose Level";
title5 justify=center font="Courier new" height=1 "Safety Population";
footnote1 justify=left font="Courier new" height=1 "Dose Level: A=14mg qd, B=14mg bid, C=35mg qd, D=35mg bid";
footnote2 "";
footnote3 justify=left font="Courier new" height=1 "Cross Reference: CRF page 3";
footnote4 justify=left font="Courier new" height=1 "MM/DD/YYYY, XXXXX.sas ";
ods escapechar= '!';
proc report data = final nowindows headskip missing split="/"
style(header)={just=left vjust=bottom protectspecialchars=off asis=on rules=none}
style(column)={axis=on }
;
columns CHARA STAT ("Dose Level A (N=XX)" ACTIVE_A PLACEBO_A) ("Dose Level B (N=XX)" ACTIVE_B PLACEBO_B)
("Dose Level C (N=XX)" ACTIVE_C PLACEBO_C);
define CHARA / display "Characteristics" left ;
define STAT / display "Statistic" left ;
define ACTIVE_A /display "STA-5326/ N (%)" ;
define PLACEBO_A /display "placebo/ N (%)" ;
define ACTIVE_B /display "STA-5326/ N (%)" ;
define PLACEBO_B /display "placebo/ N (%)" ;
define ACTIVE_C /display "STA-5326/ N (%)" ;
define PLACEBO_C /display "placebo/ N (%)" ;
run;
ods rtf close;
And it was almost correct except for the font and fontsize. So I wrote a proc template to create a new style with Journal as the parent.
proc template;
define style Styles.Custom;
parent = Styles.Journal;
replace fonts /
'TitleFont' = ("Courier New",8pt) /* Titles from TITLE statements */
'TitleFont2' = ("Courier New",8pt) /* Procedure titles ("The _____ Procedure")*/
'StrongFont' = ("Courier New",8pt)
'EmphasisFont' = ("Courier New",8pt)
'headingEmphasisFont' = ("Courier New",8pt)
'headingFont' = ("Courier New",8pt) /* Table column and row headings */
'docFont' = ("Courier New",8pt) /* Data in table cells */
'footFont' = ("Courier New",8pt) /* Footnotes from FOOTNOTE statements */
'FixedEmphasisFont' = ("Courier New",8pt)
'FixedStrongFont' = ("Courier New",8pt)
'FixedHeadingFont' = ("Courier New",8pt)
'BatchFixedFont' = ("Courier New",8pt)
'FixedFont' = ("Courier New",8pt);
end;
run;
and when the custom style that I created, this is what I get. Do level B and Dose level C gets pushed down. Actualy I am only reducing the size of the fonts and by my assumptinn I should have more space. What am I doing wrong? How do I correct this?