BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Eva
Quartz | Level 8 Eva
Quartz | Level 8

Dear all,

 

I have a Donut Chart with a legend. The optical purpose it to display the slices in a given order (variable r) and ordered Color list (goptions Colors). The legend should Display the  names (variable Status), not the numbers in a given order (variable r).

(Please don't ask the data - I get it like this from somebody else. I wrote it into a proc SQL so that you can test it.)

 

/* I get this data from somebody else */
/* For your testing I write it as SQL down */
proc sql noprint; create table work.mydata ( status char(50), anz_massnahmen num, reihenfolge num, r char(2) ) ; insert into work.mydata (status,anz_massnahmen,reihenfolge,r) values("ist umgesetzt", 10, 1, "1") values("wird umgesetzt", 10, 2, "2") values("in Aufarbeitung", 20, 3, "3") values("wird nicht umgesetzt", 20, 4, "4") values("über anderen Kanal adressiert", 10, 5, "5") ; quit;
/* Here my code starts */
/* Color list for the legend. The Colors should appear in this order */ goptions cback='cxF2F2F2' colors=('cx113388' 'cx426BB3' 'cx819CCC' 'cxC6CEE2' 'cxAAADC3');

/* Legend for the Donut */
/* The Legend values should appear in this order */ Legend1 ACROSS =1 NOFRAME LABEL=NONE POSITION = (MIDDLE RIGHT OUTSIDE) value=("ist umgesetzt" "wird umgesetzt" "in Aufarbeitung" "wird nicht umgesetzt" "über anderen Kanal adressiert") ;
/* Donut code */ PROC GCHART DATA =mydata; DONUT r / SUMVAR = anz_massnahmen TYPE = SUM LEGEND = LEGEND1 SLICE = NONE PERCENT = NONE VALUE = OUTSIDE OTHER = 4 OTHERLABEL = "Sonstige" COUTLINE = BLACK NOHEADING DONUTPCT=70 ; RUN; quit;

 

This code runs ok. Everything is as my customer wishes.

 

My code has to run for whatever data arrives. It has to be able to deal with different data and nevertheless Display the Donut with the right legend, Color list and right data order.

 

The Problem Comes when I get different data. It may occur that I get data with anz_massnahmen = 0 for some rows. For example:

 

proc sql noprint;
	create table work.mydata 
	(
	status char(50),
	anz_massnahmen num,
	reihenfolge num,
	r char(2)
	) 
	;
	insert into work.mydata (status,anz_massnahmen,reihenfolge,r)
	values("ist umgesetzt", 10, 1, "1")
	values("wird umgesetzt", 0, 2, "2")
	values("in Aufarbeitung", 20, 3, "3")
	values("wird nicht umgesetzt", 20, 4, "4")
	values("über anderen Kanal adressiert", 10, 5, "5")
	;
quit;

 

Please run this data with the aboce goptions, legend and proc gchart code.

 

What happens is that the slice for Status = "wird umgesetzt" is not displayed (as anz_massnahmen = 0 for this row) and thus the legend is no longer correct (the legend Displays "wird umgesetzt" because I use value= in the legend Statement). And the Color order is the same but now the second Color is used for the third data row. But the customer wants the second Color to always be used with r=2. So in this case the second Color should be left out from the Donut graph.

 

To solve the Problem with the legend value= I used this code:

 

proc sql noprint;
	create table work.mydata 
	(
	status char(50),
	anz_massnahmen num,
	reihenfolge num,
	r char(2)
	) 
	;
	insert into work.mydata (status,anz_massnahmen,reihenfolge,r)
	values("ist umgesetzt", 10, 1, "1")
	values("wird umgesetzt", 0, 2, "2")
	values("in Aufarbeitung", 20, 3, "3")
	values("wird nicht umgesetzt", 20, 4, "4")
	values("über anderen Kanal adressiert", 10, 5, "5")
	;
quit;

proc format;
	value $fstatus
		1 = "ist umgesetzt"
		2 = "wird umgesetzt"
		3 = "in Aufarbeitung"
		4 = "wird nicht umgesetzt"
		5 = "über anderen Kanal adressiert"
		6 = "bereits bekannt"
		;
run;

goptions cback='cxF2F2F2' colors=('cx113388' 'cx426BB3' 'cx819CCC' 'cxC6CEE2' 'cxAAADC3');
Legend1
	ACROSS =1
	NOFRAME
	LABEL=NONE
	POSITION = (MIDDLE RIGHT OUTSIDE) 
/*	value=("ist umgesetzt" "wird umgesetzt" "in Aufarbeitung" "wird nicht umgesetzt" "über anderen Kanal adressiert")*/
;

PROC GCHART DATA =mydata;
	format r $fstatus.;
	DONUT r
			/ 
			SUMVAR     = anz_massnahmen
			TYPE       = SUM
			LEGEND     = LEGEND1
			SLICE      = NONE
			PERCENT    = NONE
			VALUE      = OUTSIDE
			OTHER      = 4
			OTHERLABEL = "Sonstige"
			COUTLINE   = BLACK
			NOHEADING
			DONUTPCT=70
			;
RUN;
quit;

 

Due to the Format the legend values now correspond to the slices. The graph in itself is correct again.

 

But my customer now says the second Color is now assigned to the wrong value. (The second Color must be assigned to the data row with r=2 and not to the row with r=3).

 

I understand what the customer wants. Always the same Color for the same Status. So that the user knows from the Color what it is.

 

Can you help me with my code? How am I able to do this without knowing what data arrives?

(I tried discrete but it doesn't work.)

 

Thanx for everybody reading the whole text 🙂

Eva

1 ACCEPTED SOLUTION

Accepted Solutions
GraphGuy
Meteorite | Level 14

I don't use pies much, so this is a bit of a gray area for me, but I think this might achieve what you're wanting ...

 

I think you will want to specify your colors in pattern statements (rather than a goptions color list), and then specify all the possible slices via midpoints=. I think this way, all the slices in the midpoints list will be assigned a color, even if there isn't data for that slice being plotted.

 

Here's a simplified example demonstrating this technique:

 

pattern1 v=s c=blue;
pattern2 v=s c=green;
pattern3 v=s c=red;

 

/* a pie with no slices missing (you don't have to use midpoints) */

data foo;
length cat $20;
cat='blue slice'; value=1; output;
cat='green slice'; value=2; output;
cat='red slice'; value=3; output;
run;
proc gchart data=foo;
donut cat / type=sum sumvar=value legend;
run;

 

donut1.png

 

 

/* a pie with no cat='green slice' ... but using midpoints= you can still get the green pattern statement to be 'consumed' and the red pattern assigned to 'red slice' ... even though there is no 'green slice' in the data nor the pie */

data foo2;
length cat $20;
cat='blue slice'; value=1; output;
cat='red slice'; value=3; output;
run;
proc gchart data=foo2;
donut cat / type=sum sumvar=value legend
midpoints='blue slice' 'green slice' 'red slice';
run;

 

donut2.png

 

 

View solution in original post

3 REPLIES 3
ballardw
Super User

It has been awhile since I have done any donut charts so I am not sure this will always work but color assignments tend to be in the order data values are encountered so sorting may help. If you have character values you may have issues with default sort order with numerals so us Proc Sort with sortseq=linguistic(numeric_collation=on).

 

If any of the values are missing for a specific chart you may to insure that the group exists even if the summary variable has missing values.

GraphGuy
Meteorite | Level 14

I don't use pies much, so this is a bit of a gray area for me, but I think this might achieve what you're wanting ...

 

I think you will want to specify your colors in pattern statements (rather than a goptions color list), and then specify all the possible slices via midpoints=. I think this way, all the slices in the midpoints list will be assigned a color, even if there isn't data for that slice being plotted.

 

Here's a simplified example demonstrating this technique:

 

pattern1 v=s c=blue;
pattern2 v=s c=green;
pattern3 v=s c=red;

 

/* a pie with no slices missing (you don't have to use midpoints) */

data foo;
length cat $20;
cat='blue slice'; value=1; output;
cat='green slice'; value=2; output;
cat='red slice'; value=3; output;
run;
proc gchart data=foo;
donut cat / type=sum sumvar=value legend;
run;

 

donut1.png

 

 

/* a pie with no cat='green slice' ... but using midpoints= you can still get the green pattern statement to be 'consumed' and the red pattern assigned to 'red slice' ... even though there is no 'green slice' in the data nor the pie */

data foo2;
length cat $20;
cat='blue slice'; value=1; output;
cat='red slice'; value=3; output;
run;
proc gchart data=foo2;
donut cat / type=sum sumvar=value legend
midpoints='blue slice' 'green slice' 'red slice';
run;

 

donut2.png

 

 

Eva
Quartz | Level 8 Eva
Quartz | Level 8

Dear Robert,

 

thanx a lot. The midpoints Option did it. I didn't even have to use pattern instead of goptions Color. But additionally, I found out, the missing Option has to be set as well.

 

So this is what works: (all the code from the question, but the proc gchart as I write it here in this answer.)

 

PROC GCHART DATA =mydata;
	DONUT r
			/ 
			SUMVAR     = anz_massnahmen
			TYPE       = SUM
missing
midpoints="ist umgesetzt" "wird umgesetzt" "in Aufarbeitung" "wird nicht umgesetzt" "über anderen Kanal adressiert"
			LEGEND     = LEGEND1
			SLICE      = NONE
			PERCENT    = NONE
			VALUE      = OUTSIDE
			OTHER      = 4
			OTHERLABEL = "Sonstige"
			COUTLINE   = BLACK
			NOHEADING
			DONUTPCT=70
			;
RUN;
quit;

 

 

Best wishes

Eva

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 3 replies
  • 1606 views
  • 0 likes
  • 3 in conversation