BookmarkSubscribeRSS Feed
Anita_n
Pyrite | Level 9

Dear all,

is it possible to use explode on sgpie when creating a donut chart?

 

 

7 REPLIES 7
sbxkoenk
SAS Super FREQ

Hello @Anita_n ,

 

Thanks to your question, I have now discovered 

     proc EXPLODE

, which is completely unrelated to your question by the way. 😉

 

I can only look at the doc and I do not see any "explode" option in DONUT Statement of PROC SGPIE.

 

But I am looking at SAS 9.4 M7 doc while the SGPIE procedure is/was a preproduction feature in the SAS 9.4M6 release.
Maybe if you are using SAS VIYA, more is possible?

 

Thanks,

Koen

sbxkoenk
SAS Super FREQ

On top of my previous reply (see above message).

 

If you use GCHART Procedure with

PIE, PIE3D, and DONUT Statement

, you have access to 

EXPLODE= option.

 

Any reason why you would prefer PROC SGPIE over PROC GCHART ??

If not, use the latter to accomplish what you want.

 

Thanks,

Koen

ballardw
Super User

@sbxkoenk wrote:

On top of my previous reply (see above message).

 

If you use GCHART Procedure with

PIE, PIE3D, and DONUT Statement

, you have access to 

EXPLODE= option.

 

Any reason why you would prefer PROC SGPIE over PROC GCHART ??

If not, use the latter to accomplish what you want.

 

Thanks,

Koen


Proc Gchart would require a SAS/Graph license and OP may not have such while the SG graphics procs are part of the basic install.

 

I fought with Proc Gchart for a number of years. Didn't really miss it when SGPLOT became available (don't do Pie charts unless threatened with serious bodily harm 😉).

JeffMeyers
Barite | Level 11

This is a pie chart macro that I wrote that allows the user to "explode" out a second piechart with the "Other" categories.  I don't know if this is what you are trying to do with a donut chart, but you could add a white circle to the center to make this a donut chart.  The code could use refinement but could get you started.

 

The VAR option controls which variable sets the categories.  The OTHER_THRESHOLD determines which percentage is considered "Other" (e.g. 5 will take any group <=5% and group it into the Other slice).  RADIUS and OTHER_RADIUS determine the size of the circles for the pie chart and OTHER_SHIFT will move the second pie chart over left or right.

 

 %pie(data=sashelp.cars,var=type,other_threshold=10);

_pie.png

 

 

%macro pie(data=,var=,other_threshold=5,radius=1,other_radius=0.5,other_shift=2,
    plottype=png,plotname=_pie);
    
    data _temp;
        set &data (keep=&var rename=(&var=_var_t));
        length _var_ $200.;
        if ^missing(strip(vvalue(_var_t))) then _var_=strip(vvalue(_var_t));
        else _var_='Missing';
    run;
    
    proc freq data=_temp noprint;
        table _var_ / out=_frq;
    run;
    
    data _frq2;
        set _frq;
        by _var_;
        if first._var_ then _indx_+1;
    run;
    
    proc sql noprint;
        create table _plota as
            select a.* ,b._var_
            from (select _indx_,sum(percent) as percent from
            (select _var_,ifn(percent lt &other_threshold,.o,_indx_) as _indx_,(percent lt &other_threshold) as other,percent from _frq2)
            group by _indx_) a left join _Frq2 as b on a._indx_=b._indx_;
        create table _plotb as   
            select _var_,_indx_,percent,percent/sum(percent) as ppt,sum(percent) as othpct from _frq2 where percent lt &other_threshold;
        %local _othgrps;
        select count(*) into :_othgrps from _frq where percent lt &other_threshold;
    quit;
    data _plota2 (drop=text xtext ytext) _texta (keep=text xtext ytext);
        set _plota end=last;
        retain endpoint id;
        percent=percent/100;
        if _n_=1 and _indx_^=.o then endpoint=0;
        if _indx_=.o then do;
            id=1;
            text=strip(put(percent*100,12.0))||'%';
            xtext=0.5*cos(0);ytext=1.1*sin(0);output _texta;
            series=1;x=0;y=0;output _plota2;
            series=0;
            do i = (2*constant('pi'))*(-percent/2) to (2*constant('pi'))*(percent/2) by (2*constant('pi'))*(percent/50);
                x=&radius*cos(i);
                y=&radius*sin(i);
                output _plota2;
            end;
            series=1;output _plota2;
            endpoint=percent/2;
        end;
        else do;
            id+1;
            text=strip(put(percent*100,12.0))||'%';
            xtext=0.6*cos(2*constant('pi')*(percent/2+endpoint));ytext=0.6*sin(2*constant('pi')*(percent/2+endpoint));output _texta;
            series=1;x=0;y=0;output _plota2;  
            series=0;
            do i = (2*constant('pi'))*(endpoint) to (2*constant('pi'))*(percent+endpoint) by (2*constant('pi'))*(percent/50);
                x=&radius*cos(i);
                y=&radius*sin(i);
                output _plota2;
            end;
            if last then do;
                series=1;output _plota2;
            end;
            else do;
                series=1;output _plota2;        
            end;
            endpoint=endpoint+percent;
        end;
    run;
    %if %sysevalf(&_othgrps>0,boolean) %then %do;
        data _links;
            set _plota;
            where _indx_=.o;
            
            link=1;
            xlink=&radius*cos(constant('pi')*percent/100);
            ylink=&radius*sin(constant('pi')*percent/100);
            output;
            xlink=&other_shift+&other_radius*cos(2*constant('pi')/3);
            ylink=&other_radius*sin(2*constant('pi')/3);
            output;
            
            link=2;
            xlink=&radius*cos(constant('pi')*-percent/100);
            ylink=&radius*sin(constant('pi')*-percent/100);
            output;
            xlink=&other_shift+&other_radius*cos(4*constant('pi')/3);
            ylink=&other_radius*sin(4*constant('pi')/3);
            output;
        run;
        data _plotb2(drop=text xtext ytext) _textb (keep=text xtext ytext);
            set _plotb;
            retain endpoint id;
            if _n_=1 then endpoint=0;
            id+1;
            text=strip(put(percent,12.0))||'%';
            xtext=&other_shift+0.5*&other_radius*cos(2*constant('pi')*(ppt/2+endpoint));
            ytext=0.5*&other_radius*sin(2*constant('pi')*(ppt/2+endpoint));output _textb;
            series=1;x=&other_shift;y=0;output _plotb2;  
            series=0;
            do i = (2*constant('pi'))*(endpoint) to (2*constant('pi'))*(ppt+endpoint) by (2*constant('pi'))*(ppt/50);
                x=&other_shift+&other_radius*cos(i);
                y=&other_radius*sin(i);
                output _plotb2;
            end;
            series=1;output _plotb2;
            endpoint=endpoint+ppt;
        run;
    %end;
        
    data _text;
        set _texta %if %sysevalf(&_othgrps>0,boolean) %then %do; _textb %end;;
    run;
    data _plot;
        set _plota2 (in=a) %if %sysevalf(&_othgrps>0,boolean) %then %do; _plotb2 (in=b) %end;;
        retain lastid;
        if a then lastid=id;
        else do;
            circle=2;
            id=id+lastid;
        end;
    run;
    
    data _plot;
        merge _plot _text %if %sysevalf(&_othgrps>0,boolean) %then %do; _links %end;;
    run;
    ods path WORK.TEMPLAT(UPDATE) SASHELP.TMPLMST (READ);
    proc template;
        define statgraph _pie;
        begingraph / 
            
            %if %sysevalf(&_othgrps>0,boolean) %then %do;
                designheight=5in designwidth=10in
            %end;
            %else %do;
                designheight=5in designwidth=7in
            %end;;
        layout lattice;
            sidebar / align=right;            
                discretelegend 'p1'  / exclude=(' ') location=inside halign=right valign=center border=false across=1 valueattrs=(size=18pt)
                    displayclipped=true autoitemsize=true;
            endsidebar;
            layout overlay / walldisplay=none xaxisopts=(display=none 
                %if %sysevalf(&_othgrps>0,boolean) %then %do;
                    linearopts=(viewmin=-1.1 viewmax=%sysevalf(&other_shift+&other_radius+0.1))) 
                %end;
                %else %do;
                    linearopts=(viewmin=-1.1 viewmax=1.1)) 
                %end;
                    
                yaxisopts=(display=none linearopts=(viewmin=-1.1 viewmax=1.1));
                /*Left Pie Chart*/
                polygonplot x=eval(ifn(circle^=2,x,.)) y=y id=id / outlineattrs=(color=black pattern=1) display=(fill) group=_var_ name='p1'
                    dataskin=gloss;
                seriesplot x=eval(ifn(series=1 and circle^=2,x,.)) y=y / lineattrs=(color=black pattern=1) group=id;
                DRAWOVAL X=0 Y=0 WIDTH=2 HEIGHT=2 / display=(outline) outlineattrs=(color=black) heightunit=data 
                    drawspace=datavalue widthunit=data;
                    
                /*Right Pie Chart*/
                %if %sysevalf(&_othgrps>0,boolean) %then %do;
                    polygonplot x=eval(ifn(circle=2,x,.)) y=y id=id / outlineattrs=(color=black pattern=1) display=(fill) group=_var_ dataskin=gloss;
                    seriesplot x=xlink y=ylink / group=link lineattrs=(color=black pattern=1);
                    DRAWOVAL X=&other_shift Y=0 WIDTH=%sysevalf(2*&other_radius) HEIGHT=%sysevalf(2*&other_radius) / display=(outline) outlineattrs=(color=black) heightunit=data 
                        drawspace=datavalue widthunit=data;
                        
                    seriesplot x=eval(ifn(series=1 and circle=2,x,.)) y=y / lineattrs=(color=black pattern=1) group=id;
                %end;
                /*Percentages*/
                textplot x=xtext y=ytext text=text / textattrs=(size=16pt) position=center;
            endlayout;
        endlayout;
        endgraph;
        end;
    run;
    ods graphics / reset scale=off imagename="&plotname" imagefmt=&plottype; 
    proc sgrender data=_plot template=_pie;
    run;
    
    proc datasets nodetails nolist;
       delete _temp _temp2 _plota _plota2 _plotb _plotb2 _links _text _texta _textb  _Frq _frq2;
    quit;
%mend;
Anita_n
Pyrite | Level 9

@JeffMeyers  I was going through your code and have some few questions:

what are the values of the following

&radius 

&other_shift

&other_radius

and &_othgrps

 

 

GraphGuy
Meteorite | Level 14

If by 'explode' you mean to separate one slice out from the rest of the pie, I would recommend using SAS/Graph Proc Gchart (which has the explode= option), as Koen suggests. Proc SGpie is still pre-production.

 

Here's an example showing how to use the explode option in Proc Gchart:

http://robslink.com/SAS/democd7/pie6_info.htm 

 

 

Anita_n
Pyrite | Level 9

Dear @sbxkoenk @ballardw  Thanks for the sample solutions. I have no specific reason for wanting to use sgpie over gchart. I use mostly sgplots because I find them easier. I already have defined attrmaps which I can easily use over and over. I created a donut chart yesterday and I thought it will be interesting to explode a slice but if this is not possible then is okay. I find the explode procedure also interesting. I will have a look at that. 

 

@JeffMeyers thanks for that, it's an interesting example. I will have a look at that for other analysis.

 

 

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 7 replies
  • 987 views
  • 3 likes
  • 5 in conversation