BookmarkSubscribeRSS Feed
samp945
Obsidian | Level 7

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:

 

https://blogs.sas.com/content/graphicallyspeaking/2017/12/08/advanced-ods-graphics-applying-position...

 

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!

 

Figure100.png

 

		*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;
7 REPLIES 7
yabwon
Onyx | Level 15

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

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



DanH_sas
SAS Super FREQ

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!

samp945
Obsidian | Level 7

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!

 

Figure100.png

 

		*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;
DanH_sas
SAS Super FREQ

On the TEXT statement, try add these two options:

  1. STRIP -- this option strips extra spaces from the text. I think that is why you are getting a difference between the LEFT and RIGHT positioned text
  2. PAD=10px -- This will pad out the text by 10 px. You can adjust this to taste.
ballardw
Super User

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?

 

 

samp945
Obsidian | Level 7

Thanks for your help, @ballardw 

 

The dataset is quite large so I have attached the code as a text file.

Ksharp
Super User

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;

Ksharp_0-1711076913230.png

 

 

SAS Innovate 2025: Register Now

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!

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 7 replies
  • 1559 views
  • 0 likes
  • 5 in conversation