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
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
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
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;
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!
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?