%let name=radarmap; filename odsout '.'; /* color of the radar charts */ %let radcolor=white; data mydata; input x y colorval val1 val2 val3; /* Add a variable to use as the area= in the block map */ id = trim(left(x))||','||trim(left(y)); datalines; 3 0 5 3 8 8 4 0 6 5 10 9 2 1 5 5 10 9 3 1 6 5 9 8 4 1 5 5 10 9 5 1 6 5 10 9 1 2 7 5 10 7 2 2 6 5 9 8 3 2 5 5 10 8 4 2 5 5 10 9 5 2 6 5 10 9 6 2 7 5 10 9 0 3 7 5 9 9 1 3 6 5 10 9 2 3 5 5 10 9 3 3 5 5 10 8 4 3 5 5 9 8 5 3 5 5 10 9 6 3 6 5 10 9 7 3 7 5 10 9 0 4 7 5 9 9 1 4 6 5 10 8 2 4 5 5 10 9 3 4 5 5 10 9 4 4 5 5 9 9 5 4 5 5 10 9 6 4 6 5 9 8 7 4 7 5 10 9 1 5 7 5 10 9 2 5 6 5 10 9 3 5 5 5 10 9 4 5 6 5 8 9 5 5 8 2 9 6 6 5 8 2 9 5 2 6 6 5 10 9 3 6 6 5 10 9 4 6 7 5 10 4 5 6 8 5 10 10 3 7 7.5 2 9 9 4 7 7 2 10 9 ; run; /* Add html charttips to the data */ data mydata; set mydata; length html $ 254; html= 'title='||quote( 'id: (x,y) '||trim(left(id))||'0D'x|| 'val1: '||trim(left(val1))||'0D'x|| 'val2: '||trim(left(val2))||'0D'x|| 'val3: '||trim(left(val3))||'0D'x|| 'colorval: '||trim(left(colorval)) )|| ' href="radarmap_info.htm"'; run; /* Now, create a map */ data mymap; set mydata; /* Output the 4 coordinates for a square map area */ output; x=x+1; output; y=y+1; output; x=x-1; output; run; proc sql; /* Now, create a 'centers' dataset with the estimated centers of each area */ create table centers as select unique id, avg(x) as x, avg(y) as y from mymap group by id; /* and merge in the response data values... */ create table centers as select centers.*, mydata.* from centers left join mydata on centers.id=mydata.id; quit; run; /* This is the max number for each value (used to 'normalize' the data) */ %let normval1=5; %let normval2=10; %let normval3=10; data centers; set centers; normval1=val1/&normval1; normval2=val2/&normval2; normval3=val3/&normval3; run; /* Maximum spoke radius */ %let max_size=.5; /* Create dataset containing spokes of the glyphs */ data spokes; set centers; length function color $8; xsys='2'; ysys='2'; hsys='3'; when='A'; size=.1; /* thickness of the line */ /* First spoke of star/radar chart is at 90 degrees */ /* 90 degrees = noon clock position */ /* convert degrees to radians, since sas sin() and cos() operate on radians */ angledeg=90; anglerad=( (2*3.14)/360 )*(angledeg); /* Move to center of glyph */ function='move'; anno_x=x; anno_y=y; output; /* Calculate the end of a spoke, and draw a line to it */ color='blue'; y_offset = ((normval1*&max_size) * sin(anglerad)); x_offset = ((normval1*&max_size) * cos(anglerad)); function='draw'; anno_x = x + x_offset; anno_y = y + y_offset; output; /* 2nd spoke of star/radar chart is at 90+120=210 degrees (assuming 3 spokes) */ angledeg=210; anglerad=( (2*3.14)/360 )*(angledeg); function='move'; anno_x=x; anno_y=y; output; color='red'; y_offset = ((normval2*&max_size) * sin(anglerad)); x_offset = ((normval2*&max_size) * cos(anglerad)); function='draw'; anno_x = x + x_offset; anno_y = y + y_offset; output; /* 3rd spoke of star/radar chart is at 210+120=330 (assuming 3 spokes) */ angledeg=330; anglerad=( (2*3.14)/360 )*(angledeg); function='move'; anno_x=x; anno_y=y; output; color='green'; y_offset = ((normval3*&max_size) * sin(anglerad)); x_offset = ((normval3*&max_size) * cos(anglerad)); function='draw'; anno_x = x + x_offset; anno_y = y + y_offset; output; run; data spokes; set spokes; x=anno_x; y=anno_y; run; /* Create dataset containing the polygon connecting the spokes for the glyphs */ data edges; set centers; length function color $8; xsys='2'; ysys='2'; hsys='3'; when='A'; color="&radcolor"; style='msolid'; /* First spoke of star/radar chart is at 0 degrees */ /* 90 degrees = noon clock position */ /* convert degrees to radians, since sas sin() and cos() operate on radians */ angledeg=90; anglerad=( (2*3.14)/360 )*(angledeg); /* Calculate the end of a spoke, and draw a line to it */ y_offset = ((normval1*&max_size) * sin(anglerad)); x_offset = ((normval1*&max_size) * cos(anglerad)); function='poly'; anno_x = x + x_offset; anno_y = y + y_offset; output; /* 2nd spoke of star/radar chart is at 210 degrees (assuming 3 spokes) */ angledeg=210; anglerad=( (2*3.14)/360 )*(angledeg); y_offset = ((normval2*&max_size) * sin(anglerad)); x_offset = ((normval2*&max_size) * cos(anglerad)); function='polycont'; anno_x = x + x_offset; anno_y = y + y_offset; output; /* 3rd spoke of star/radar chart (assuming 3 spokes) */ angledeg=330; anglerad=( (2*3.14)/360 )*(angledeg); y_offset = ((normval3*&max_size) * sin(anglerad)); x_offset = ((normval3*&max_size) * cos(anglerad)); function='polycont'; anno_x = x + x_offset; anno_y = y + y_offset; output; run; data edges; set edges; x=anno_x; y=anno_y; run; data glyphs; set edges spokes; run; /* annotate a graphical spoke-legend */ data annolegend; length color function $12 text $20; xsys='3'; ysys='3'; hsys='3'; when='A'; x=15; y=20; /* use the 'pie' function to draw the spoke at the appropriate angle */ function='pie'; size=5; angle=90; color='blue'; output; angle=210; color='red'; output; angle=320; color='green'; output; /* now, place some labels at end of the spokes */ color='black'; angle=0; size=4; style=''; x=15; y=25; function='label'; position='2'; text='Val 1'; output; x=11; y=18; function='label'; position='D'; text='Val 2'; output; x=19; y=18; function='label'; position='F'; text='Val 3'; output; run; goptions device=png; goptions border cback=grayee; ODS LISTING CLOSE; ODS HTML path=odsout body="&name..htm" (title="SAS/Graph radar/star chart on wafer map") style=sasweb; goptions ftitle="albany amt" ftext="albany amt" htitle=7pct htext=4pct; /* left-justify the legend text so it's closer to it's color chicklet, and make the color chicklets a little more square */ legend1 value=(justify=left) shape=bar(4,1.2) position=(bottom right) across=1 mode=share; pattern1 v=s c=cxc6dbef; pattern2 v=s c=cxc7e9c0; pattern3 v=s c=cxffffcc; pattern4 v=s c=cxfed976; pattern5 v=s c=cxfc9272; title1 ls=1.5 "Radar/Star-Charts on Wafer Map"; footnote2 box=1 bcolor=&radcolor c=blue '---' c=black ' Val 1 ' c=red '---' c=black ' Val 2 ' c=green '---' c=black ' Val 3'; proc gmap data=mydata map=mymap all anno=glyphs; id id; choro colorval / discrete coutline=black legend=legend1 anno=annolegend html=html des='' name="&name"; run; quit; ODS HTML CLOSE; ODS LISTING;