Hello all,
I'm creating a series graph with a group variable and using the DATALABEL option to add quartile values to the graph. I believe SAS uses an algorithm to automatically avoid colliding as described in this blog post and elsewhere:
However, the quartile datalabel values that I created are colliding for the two groups.
Why isn't the automatic collision avoidance working for me?
I think I can use the advice at the above-linked blog to manually alter datalabel positions, but I need to produce quite a few of these graphs with different data and would like to use the automatic collision avoidance if possible.
Thanks for your help!
*GRAPH - All;
ods listing gpath='\\Figures\' image_DPI=300;
ods graphics / reset
height=6.5in imagename="Figure100&Z" imagefmt=PNG ATTRPRIORITY=NONE ANTIALIASMAX=378300;
Footnote justify=left height=1.2 font="Times New Roman" "Figure X.XX. Survival Function";
Title;
proc sgplot data=SurvivalPlot noborder;
series x=Time y=Survival /
lineattrs=(pattern=solid)
Group=Stratum
datalabel=Years
datalabelattrs=(size=10)
Name='S';
scatter x=Time y=Quartiles /
markerattrs=(symbol=circle size=7)
name='Q';
keylegend 'Q' /
location=inside
position=right
Valueattrs=(Size=10);
yaxis label="Survival Probability"
grid values=(0 to 1 by 0.10);
xaxis label="Years"
grid values=(0 to 20 by 2);
run;
How about creating input data set with two separate variables, one for each "Stratum" value, and then create two SERIES plots, one with "DATALABELPOS=LEFT" and other with "DATALABELPOS=RIGHT" ?
{EDIT:}
data have;
do Time=1 to 5;
Quartiles1 = time;
Quartiles2 = time;
Quartiles1lab = "A" !! put(time*10,5.2-l);
Quartiles2lab = "B" !! put(time*20,5.2-l);
output;
end;
run;
proc sgplot data=have;
scatter x=Time y=Quartiles1 / datalabel=Quartiles1lab
markerattrs=(symbol=circle size=7) DATALABELPOS=LEFT;
scatter x=Time y=Quartiles2 / datalabel=Quartiles2lab
markerattrs=(symbol=circle size=7) DATALABELPOS=RIGHT;
run;
Bart
Another option would be to use your existing data structure, but add a TEXT plot so that you can control the label positions from your data. The code would look something like the following.
proc sgplot data=SurvivalPlot noborder;
series x=Time y=Survival /
lineattrs=(pattern=solid)
Group=Stratum
Name='S';
scatter x=Time y=Quartiles /
markerattrs=(symbol=circle size=7)
name='Q';
text x=Time y=Survival text=years / group=stratum
textattrs=(size=10) position=PositionVar;
keylegend 'Q' /
location=inside
position=right
Valueattrs=(Size=10);
yaxis label="Survival Probability"
grid values=(0 to 1 by 0.10);
xaxis label="Years"
grid values=(0 to 20 by 2);
run;
You would just need to add a PositionVar to your data specifying where you want the each label (LEFT, RIGHT, TOPRIGHT, BOTTOMLEFT, etc.).
Hope this helps!
Thanks for the great suggestions, @DanH_sas and @yabwon !
I used Dan's strategy and I am almost there. Any ideas on why the LEFT datalabel wants to sit exactly on the line? Is there a way to pad it over to the left a little bit?
Thanks again!
*GRAPH - All;
ods listing gpath='\\Figures\' image_DPI=300;
ods graphics / reset
height=6.5in imagename="Figure100&Z" imagefmt=PNG ATTRPRIORITY=NONE ANTIALIASMAX=378300;
Footnote justify=left height=1.2 font="Times New Roman" "Figure X.XX. Survival Function";
Title;
proc sgplot data=SurvivalPlotOffType noborder;
series x=Time y=Survival /
lineattrs=(pattern=solid)
Group=Stratum
Name='S';
scatter x=Time y=Quartiles /
markerattrs=(symbol=circle size=7)
name='Q';
text x=Time y=Quartiles text=Years /
group=stratum
textattrs=(size=10)
position=PositionVar;
keylegend 'Q' /
location=inside
position=right
Valueattrs=(Size=10);
yaxis label="Survival Probability"
grid values=(0 to 1 by 0.10);
xaxis label="Years"
grid values=(0 to 20 by 2);
run;
On the TEXT statement, try add these two options:
Can you share your plot data set?
Instructions here: https://communities.sas.com/t5/SAS-Communities-Library/How-to-create-a-data-step-version-of-your-dat... will show how to turn an existing SAS data set into data step code that can be pasted into a forum code box using the </> icon or attached as text to show exactly what you have and that we can test code against.
I'm wondering if you are getting something related to different size plot elements, text and symbol combined with the default justification of numeric values.
@samp945 wrote:
Thanks for the great suggestions, @DanH_sas and @yabwon !
I used Dan's strategy and I am almost there. Any ideas on why the LEFT datalabel wants to sit exactly on the line? Is there a way to pad it over to the left a little bit?
Thanks for your help, @ballardw
The dataset is quite large so I have attached the code as a text file.
You could put these datalabel into a SCATTER statement.
data have;
call streaminit(123);
do Time=1 to 100;
Group=1;
x=rand('uniform');
y=pdf('normal',x);
_x=.;_y=.;year=.;
if Time in (2 3 5 20 40 80 95 99) then do;_x=x;_y=y;year=2.45;end;
output;
Group=2;
x=x+0.005;
y=y+0.001;
_x=.;_y=.;year=.;
if Time in (2 3 5 20 40 80 95 99) then do;_x=x;_y=y;year=2.45;end;
output;
end;
run;
proc sort data=have ;by group x;run;
proc sgplot data=have noborder;
series x=x y=y /lineattrs=(pattern=solid) Group=Group;
scatter x=_x y=_y/datalabel=year group=group ;
run;
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.