I read the macro at its entirety starting with
%MACRO ANNOMAC(P1);
and ran below.
data south_korea; set mapsgfk.south_korea; run;
data south_korea_attr; set mapsgfk.south_korea_attr; run;
%macro maplabel(south_korea,south_korea_attr,maggie,ID1NAME,ID1 ID,
font=swiss,color=black,size=2,hsys=3,segonly=);
This gave me an error:
ERROR: Expecting comma (to separate macro parameters) or close parenthesis (to end parameter
list) but found: ID
ERROR: A dummy macro will be compiled.
However, the instruction in the Macro said
/* <ids> Space-separated list of IDs that the map and attr */
and i specified ID1 ID separated by space in the macro call as shown below. I still don't understand.
%macro maplabel(south_korea,south_korea_attr,maggie,ID1NAME,ID1 ID,
font=swiss,color=black,size=2,hsys=3,segonly=);
the whole macro below;
data south_korea; set mapsgfk.south_korea; run;
data south_korea_attr; set mapsgfk.south_korea_attr; run;
%MACRO ANNOMAC(P1);
/*********************************************************************/
/* */
/* MACRO: ANNOMAC */
/* */
/* USAGE: %ANNOMAC(NOMSG) */
/* */
/* */
/* If ANNOMAC is called without the NOMSG parameter, */
/* a message is displayed on the log that the ANNOTATE */
/* macros are available, and that help is available by */
/* calling the %HELPANO macro. If the NOMSG parameter is */
/* specified, no messages are displayed. */
/* */
/* */
/* DESCRIPTION: */
/* This macro compiles and makes available all of the */
/* ANNOTATE macros documented in the SAS/GRAPH Users Guide. */
/* */
/* NOTES: */
/* Use of %ANNOMAC causes all of the ANNOTATE macros to be */
/* compiled. If this is undesirable, you should select the */
/* macros you want to use and place them in a separate member */
/* in your AUTOCALL library. */
/* */
/*********************************************************************/
%IF %UPCASE(&P1)=HELP %THEN %DO;
%PUT %NRSTR( USAGE: %ANNOMAC(NOMSG););
%PUT %NRSTR( );
%PUT %NRSTR(This macro causes all of the ANNOTATE macros documented);
%PUT %NRSTR(in the SAS/GRAPH USERS GUIDE, Version 6 Edition,);
%PUT %NRSTR(to be made available. Each of the macros can then be);
%PUT %NRSTR(used by calling them as documented in the USERS GUIDE.);
%PUT %NRSTR( );
%PUT %NRSTR(If %ANNOMAC is called without any parameters,);
%PUT %NRSTR(a message is displayed on the log that the ANNOTATE);
%PUT %NRSTR(macros are available, and that help is available by);
%PUT %NRSTR(calling the %HELPANO macro. If the NOMSG parameter is);
%PUT %NRSTR(specified, no messages are displayed.);
%PUT %NRSTR( );
%END;
%if &p1= %then %do;
%PUT %NRSTR( );
%PUT %NRSTR(*** ANNOTATE macros are now available ***) ;
%PUT %NRSTR( );
%PUT %NRSTR( For further information on ANNOTATE macros, enter,) ;
%PUT %NRSTR( %HELPANO(macroname), (for specific macros));
%PUT %NRSTR( %HELPANO(ALL), (for information on all macros));
%PUT %NRSTR( or %HELPANO (for a list of macro names));
%PUT %NRSTR( );
%end;
%MEND ANNOMAC;
%MACRO ARROW( X1, Y1, X2, Y2, COLIN, LINE, SIZE, ANGLE, STYLE);
/*--------------------------------------------------------------------*/
/* DRAW an arrow from (X1,Y1) to (X2,Y2). */
/* SIZE determines the arrow width */
/* STYLE determines the arrow head style (open, closed, filled) */
/* COLIN determines the arrow color */
/* LINE determines the length of the arrow head lines */
/* ANLGE determines the angle of the arrow */
/*--------------------------------------------------------------------*/
%move ( &x1, &y1 );
x=&x2; y=&y2; size=&size; style="&style"; color="&colin"; line=&line; angle=∠
FUNCTION="ARROW"; output;
%MEND ARROW;
%MACRO sequenc( seq );
/*--------------------------------------------------------------------*/
/* Definition of ANNOTATE generation sequence. */
/*--------------------------------------------------------------------*/
IF UPCASE("&seq")='AFTER' OR UPCASE("&seq")=:'A' THEN WHEN = "A";
ELSE WHEN = "B";
%MEND sequenc;
%MACRO sequence( seq );
/*-------------------------------------------------------------------*/
/* Definition of ANNOTATE generation sequence. */
/*-------------------------------------------------------------------*/
IF UPCASE("&seq")='AFTER' OR UPCASE("&seq")=:'A' THEN WHEN = "A";
ELSE WHEN = "B";
%MEND sequence;
%MACRO system( xs, ys, hs );
/*--------------------------------------------------------------------*/
/* Definition of ANNOTATE reference systems. */
/*--------------------------------------------------------------------*/
XSYS = "&xs"; YSYS = "&ys"; HSYS = "&hs";
%MEND system;
%MACRO comment( txt );
/*--------------------------------------------------------------------*/
/* Places descriptive text string into ANNOTATE observation stream. */
/* */
/* NOTE: This function will cause a LENGTH to be assigned to the TEXT */
/* variable, due to the nature of the DATA step. Insert a */
/* LENGTH TEXT $ nnn. ; */
/* statement into the DATA step if this is undesirable. */
/* */
/*--------------------------------------------------------------------*/
TEXT=&txt;
FUNCTION = "COMMENT "; output;
TEXT=" ";
%MEND comment;
%MACRO dclanno;
/*--------------------------------------------------------------------*/
/* Set up required variable lengths. */
/* Assure X and Y variables are in the dataset. */
/* Assure all variables in LENGTH statements are referenced. */
/*--------------------------------------------------------------------*/
LENGTH STYLE $32;
LENGTH FUNCTION COLOR $16;
LENGTH XSYS YSYS HSYS $ 1;
LENGTH WHEN POSITION $ 1;
RETAIN XSYS YSYS HSYS;
X = . ;
Y = . ;
STYLE = " ";
POSITION = "5";
COLOR = " ";
FUNCTION = " ";
%system( 4, 4, 4 );
%sequence( BEFORE );
%MEND dclanno;
%MACRO move( x1, y1 );
/*--------------------------------------------------------------------*/
/* MOVE to the requested ( X1,Y1 ) coordinate. */
/*--------------------------------------------------------------------*/
X = &x1;
Y = &y1;
FUNCTION = "MOVE "; output;
%MEND move;
%MACRO draw( x1, y1, colin, lintyp, width );
/*--------------------------------------------------------------------*/
/* DRAW a line to the requested ( X1,Y1 ) coordinate. */
/*--------------------------------------------------------------------*/
X = &x1;
Y = &y1;
LINE = &lintyp;
SIZE = &width;
IF "&colin" =: '*' THEN ; ELSE color = "&colin" ;
FUNCTION = "DRAW "; output;
%MEND draw;
%MACRO label( x1, y1, txt, coltxt, ang, rot, hgt, font, pos );
/*--------------------------------------------------------------------*/
/* Place the TXT string at ( X1,Y1 ). */
/* */
/* NOTE: Literal text MUST be enclosed in quotes, otherwise the TEXT */
/* variable will be assigned the value of the variable named in */
/* the symbolic macro parameter. DATA step errors will occur if */
/* one of these two conditions is not met. */
/*--------------------------------------------------------------------*/
X = &x1;
Y = &y1;
ANGLE = ∠
ROTATE = &rot;
SIZE = &hgt;
STYLE = "&font";
TEXT = &txt;
IF "&pos" =: '*' THEN ; ELSE POSITION = "&pos" ;
IF "&coltxt" =: '*' THEN ; ELSE color = "&coltxt";
FUNCTION = "LABEL "; output;
%MEND label;
%MACRO rect( x1, y1, x2, y2, colin, lintyp, width );
/*--------------------------------------------------------------------*/
/* Draw a rectangle. Non-fillable definition. */
/* */
/* NOTE: ( X1,Y1 ) and ( X2,Y2 ) are opposing corners. */
/*--------------------------------------------------------------------*/
IF "&colin" =: '*' THEN ; ELSE color = "&colin" ;
LINE = &lintyp;
SIZE = &width;
x=&x1; y=&y1; function="POLYLINE"; output;
x=&x2; y=&y1; function="POLYCONT"; output;
x=&x2; y=&y2; function="POLYCONT"; output;
x=&x1; y=&y2; function="POLYCONT"; output;
x=&x1; y=&y1; function="POLYCONT"; output;
%MEND rect;
%MACRO bar( x1, y1, x2, y2, color, bartyp, pattern );
/*--------------------------------------------------------------------*/
/* Draw a rectangle. Fillable definition. */
/* */
/* NOTE: ( X1,Y1 ) and ( X2,Y2 ) are opposing corners. */
/*--------------------------------------------------------------------*/
IF "&color" =: '*' THEN ; ELSE color = "&color" ;
%move ( &x1, &y1 );
X = &x2;
Y = &y2;
D8U2M1M6 = -1;
LINE = &bartyp;
STYLE = "&pattern";
IF ( SIZE > 0 ) THEN DO; D8U2M1M6 = SIZE; SIZE = 0; END;
ELSE SIZE = 0;
FUNCTION = "BAR "; output;
IF ( D8U2M1M6 > 0 ) THEN SIZE = D8U2M1M6; DROP D8U2M1M6;
%MEND bar;
%MACRO bar2( x1, y1, x2, y2, color, bartyp, pattern, width );
/*--------------------------------------------------------------------*/
/* Draw a rectangle. Fillable definition. */
/* */
/* NOTE: ( X1,Y1 ) and ( X2,Y2 ) are opposing corners. */
/*--------------------------------------------------------------------*/
IF "&color" =: '*' THEN ; ELSE color = "&color" ;
%move ( &x1, &y1 );
X = &x2;
Y = &y2;
LINE = &bartyp;
STYLE = "&pattern";
SIZE = &width;
FUNCTION = "BAR "; output;
%MEND bar2;
%MACRO circle( x1, y1, rad, colin );
/*--------------------------------------------------------------------*/
/* Draw a circle with center at ( X1,Y1 ) of radius RAD. */
/*--------------------------------------------------------------------*/
X = &x1;
Y = &y1;
LINE = 0;
ANGLE = 0.00;
ROTATE = 360.00;
SIZE = &rad;
STYLE = "EMPTY";
IF "&colin" =: '*' THEN ; ELSE color = "&colin";
FUNCTION = "PIE"; output;
%MEND circle;
%MACRO slice( x1, y1, ang, rot, rad, color, pattern, ltyp );
/*--------------------------------------------------------------------*/
/* Define a pie slice. */
/* Center at ( X1,Y1 ), radius of RAD, starting angle of ANG, with a */
/* traverse angle of ROT. LTYP defines type of boundary to draw. */
/* */
/* NOTE: LTYP must be defined by literal strings as listed below */
/* */
/* Setting LTYP to WHOLE is a special case in the macro, */
/* and causes the overriding of specified ANG and ROT values. */
/* */
/* See documentation for special ANG/ROT value handling. */
/* */
/*--------------------------------------------------------------------*/
%LET lntp= %UPCASE("<yp");
%IF %INDEX(&lntp,WHOLE) > 0 %THEN %STR( LINE = 0;) ;
%ELSE %IF %INDEX(&lntp,LEAD) > 0 %THEN %STR( LINE = 1;) ;
%ELSE %IF %INDEX(&lntp,TRAIL) > 0 %THEN %STR( LINE = 2;) ;
%ELSE %IF %INDEX(&lntp,BOTH) > 0 %THEN %STR( LINE = 3;) ;
%ELSE %IF %INDEX(&lntp,NONE) > 0 %THEN %STR( LINE = 0;) ;
%ELSE %STR( LINE = 3;) ;
X = &x1;
Y = &y1;
%IF %INDEX(&lntp,WHOLE) > 0
%THEN %DO;
%STR( ANGLE = 0; );
%STR( ROTATE = 360; );
%END;
%ELSE %DO;
%STR( ANGLE = ∠ );
%STR( ROTATE = &rot; );
%END;
SIZE = &rad;
STYLE = "&pattern";
IF "&color" =: '*' THEN ; ELSE color = "&color";
FUNCTION = "PIE "; output;
%MEND slice;
%MACRO piexy( ang, mul );
/*--------------------------------------------------------------------*/
/* Return coordinates along the radius of a previously defined pie. */
/*--------------------------------------------------------------------*/
X = .;
Y = .;
SIZE = &mul;
ANGLE = ∠
FUNCTION = "PIEXY "; output;
%MEND piexy;
%MACRO poly ( x1, y1, color, pattern, lintyp );
/*--------------------------------------------------------------------*/
/* Begin definition of a polygon. */
/*--------------------------------------------------------------------*/
X = &x1;
Y = &y1;
D8U2M1M6= -1;
LINE = &lintyp;
STYLE = "&pattern";
IF ( SIZE > 0 ) THEN DO; D8U2M1M6 = SIZE; SIZE = 0; END;
ELSE SIZE = 0;
IF "&color" =: '*' THEN ; ELSE color = "&color" ;
FUNCTION = "POLY "; output;
IF ( D8U2M1M6 > 0 ) THEN SIZE = D8U2M1M6; DROP D8U2M1M6;
%MEND poly;
%MACRO poly2 ( x1, y1, color, pattern, lintyp, width );
/*--------------------------------------------------------------------*/
/* Begin definition of a polygon. */
/*--------------------------------------------------------------------*/
X = &x1;
Y = &y1;
LINE = &lintyp;
STYLE = "&pattern";
SIZE = &width;
IF "&color" =: '*' THEN ; ELSE color = "&color" ;
FUNCTION = "POLY "; output;
%MEND poly2;
%MACRO polylin ( x1, y1, color, lintyp, width);
/*--------------------------------------------------------------------*/
/* Begin definition of a polyline. */
/*--------------------------------------------------------------------*/
X = &x1;
Y = &y1;
LINE = &lintyp;
SIZE = &width;
IF "&color" =: '*' THEN ; ELSE color = "&color" ;
FUNCTION = "POLYLINE"; output;
%MEND polylin;
%MACRO polyline ( x1, y1, color, lintyp, width);
/*--------------------------------------------------------------------*/
/* Begin definition of a polyline. */
/*--------------------------------------------------------------------*/
X = &x1;
Y = &y1;
LINE = &lintyp;
SIZE = &width;
IF "&color" =: '*' THEN ; ELSE color = "&color" ;
FUNCTION = "POLYLINE"; output;
%MEND polyline;
%MACRO polycon ( x1, y1, colin );
/*--------------------------------------------------------------------*/
/* Continue definition of a polygon. */
/*--------------------------------------------------------------------*/
X = &x1;
Y = &y1;
IF "&colin" =: '*' THEN ; ELSE color = "&colin";
FUNCTION = "POLYCONT"; output;
%MEND polycon;
%MACRO polycont ( x1, y1, colin );
/*--------------------------------------------------------------------*/
/* Continue definition of a polygon. */
/*--------------------------------------------------------------------*/
X = &x1;
Y = &y1;
IF "&colin" =: '*' THEN ; ELSE color = "&colin";
FUNCTION = "POLYCONT"; output;
%MEND polycont;
%MACRO frame ( colin, lintyp, width, pattern );
/*--------------------------------------------------------------------*/
/* Draw a frame around active coordinate system. */
/*--------------------------------------------------------------------*/
X = . ;
Y = . ;
IF "&colin" =: '*' THEN ; ELSE color = "&colin";
STYLE = "&pattern";
LINE= &lintyp;
SIZE= &width;
FUNCTION = "FRAME "; output;
%MEND frame;
%MACRO scale( ptx,pty, xmin,ymin, xmax,ymax, vxmin,vymin, vxmax,vymax );
/*--------------------------------------------------------------------*/
/* */
/* scales input coordinates ( ptx,pty ) into a requested range */
/* */
/* vxmin,vymin are the output range minimums ( target ) */
/* vxmax,vymax are the output range maximums ( target ) */
/* */
/* xmin,ymin are the input range minimums ( source ) */
/* xmax,ymax are the input range maximums ( source ) */
/* */
/* NOTE: ABS(minimum) MAY NOT EQUAL ABS(maximum). */
/* */
/* NO OBSERVATION IS OUTPUT BY THIS MACRO. */
/* */
/*--------------------------------------------------------------------*/
%LET f1 = ( (&vxmax-&vxmin) / (&xmax-&xmin) );
%LET f2 = ( (&vymax-&vymin) / (&ymax-&ymin) );
X = &f1 * (&ptx-&xmin);
Y = &f2 * (&pty-&ymin);
%MEND scale;
%MACRO scalet(ptx,pty, xmin,ymin, xmax,ymax, vxmin,vymin, vxmax,vymax);
/*--------------------------------------------------------------------*/
/* */
/* scales input coordinates ( ptx,pty ) into a requested range and */
/* automatically controls origin displacement */
/* */
/* */
/* vxmin,vymin are the output range minimums ( target ) */
/* vxmax,vymax are the output range maximums ( target ) */
/* */
/* xmin,ymin are the input range minimums ( source ) */
/* xmax,ymax are the input range maximums ( source ) */
/* */
/* NOTE: ABS(minimum) MAY NOT EQUAL ABS(maximum). */
/* */
/* NO OBSERVATION IS OUTPUT BY THIS MACRO. */
/* */
/*--------------------------------------------------------------------*/
%LET f1 = ( (&vxmax-&vxmin) / (&xmax-&xmin) );
%LET f2 = ( (&vymax-&vymin) / (&ymax-&ymin) );
X = &f1 * (&ptx-&xmin) + &vxmin ;
Y = &f2 * (&pty-&ymin) + &vymin ;
%MEND scalet;
%MACRO push;
/*--------------------------------------------------------------------*/
/* PUSH values (XLAST,YLAST),(XLSTT,YLSTT) onto a LIFO system stack. */
/*--------------------------------------------------------------------*/
X = . ;
Y = . ;
FUNCTION="PUSH "; output;
%MEND push;
%MACRO pop;
/*--------------------------------------------------------------------*/
/* POP values (XLAST,YLAST),(XLSTT,YLSTT) from the LIFO system stack. */
/*--------------------------------------------------------------------*/
X = . ;
Y = . ;
FUNCTION="POP "; output;
%MEND pop;
%MACRO swap;
/*--------------------------------------------------------------------*/
/* SWAP values (XLAST,YLAST) and (XLSTT,YLSTT). */
/* Does NOT affect values on LIFO system stack. */
/*--------------------------------------------------------------------*/
X = . ;
Y = . ;
FUNCTION="SWAP "; output;
%MEND swap;
%MACRO txt2cnt;
/*--------------------------------------------------------------------*/
/* COPY values (XLSTT,YLSTT) into (XLAST,YLAST). */
/* Does NOT affect values on LIFO system stack. */
/*--------------------------------------------------------------------*/
X = . ;
Y = . ;
FUNCTION = "TXT2CNTL"; output;
%MEND txt2cnt;
%MACRO txt2cntl;
/*--------------------------------------------------------------------*/
/* COPY values (XLSTT,YLSTT) into (XLAST,YLAST). */
/* Does NOT affect values on LIFO system stack. */
/*--------------------------------------------------------------------*/
X = . ;
Y = . ;
FUNCTION = "TXT2CNTL"; output;
%MEND txt2cntl;
%MACRO cntl2tx;
/*--------------------------------------------------------------------*/
/* COPY values (XLAST,YLAST) into (XLSTT,YLSTT). */
/* Does NOT affect values on LIFO system stack. */
/*--------------------------------------------------------------------*/
X = . ;
Y = . ;
FUNCTION = "CNTL2TXT"; output;
%MEND cntl2tx;
%MACRO cntl2txt;
/*--------------------------------------------------------------------*/
/* COPY values (XLAST,YLAST) into (XLSTT,YLSTT). */
/* Does NOT affect values on LIFO system stack. */
/*--------------------------------------------------------------------*/
X = . ;
Y = . ;
FUNCTION = "CNTL2TXT"; output;
%MEND cntl2txt;
%MACRO draw2tx ( colin, lintyp, width );
/*--------------------------------------------------------------------*/
/* DRAW a line from (XLAST,YLAST) to (XLSTT,YLSTT). */
/* Does NOT affect values on LIFO system stack. */
/*--------------------------------------------------------------------*/
X = . ;
Y = . ;
SIZE = &width;
LINE = &lintyp;
IF "&colin" =: '*' THEN ; ELSE color = "&colin" ;
FUNCTION = "DRAW2TXT"; output;
%MEND draw2tx;
%MACRO draw2txt ( colin, lintyp, width );
/*--------------------------------------------------------------------*/
/* DRAW a line from (XLAST,YLAST) to (XLSTT,YLSTT). */
/* Does NOT affect values on LIFO system stack. */
/*--------------------------------------------------------------------*/
X = . ;
Y = . ;
SIZE = &width;
LINE = &lintyp;
IF "&colin" =: '*' THEN ; ELSE color = "&colin" ;
FUNCTION = "DRAW2TXT"; output;
%MEND draw2txt;
%MACRO line( x1, y1, x2, y2, colin, lintyp, width );
/*--------------------------------------------------------------------*/
/* DRAW a line from (X1,Y1) to (X2,Y2). */
/* Simplified version supplying the invisible move instruction. */
/*--------------------------------------------------------------------*/
IF "&colin" =: '*' THEN ; ELSE color = "&colin" ;
%move( &x1, &y1 );
%draw( &x2, &y2, &colin, &lintyp, &width );
%MEND line;
/*********************************************************************/
/* WEBOUT Utility macros */
/*********************************************************************/
/*********************************************************************/
/* */
/* MACRO: AREATAG */
/* */
/* DESCRIPTION: */
/* This macro uses a SAS dataset produced by the WEBOUT dataset */
/* option of SAS/GRAPH procedures to write HTML AREA tags fo r */
/* a HTML imagemap. */
/* */
/* USAGE: %AREATAG; */
/* */
/* NOTES: */
/* For use in a data step processing a WEBOUT dataset. This macro */
/* writes a HTML AREA tag based on the current WEBOUT dataset */
/* observation to the current output file */
/* */
/*********************************************************************/
%macro areatag;
do;
if shape='RECT'
then
put '<AREA SHAPE=RECT COORDS="'
x1 4. ',' y1 4. ',' x2 4. ',' y2 4. '" '
link $varying. length '>';
else
if shape='POLY'
then do;
put '<AREA SHAPE=POLY COORDS="' @;
do i=1 to nxy - 1;
new=compress(put(x{i},4.)||','||put(y{i},4.)||',');
put new @;
end;new=compress(put(x{nxy},4.)||','||put(y{nxy},4.));
put new '"'
link $varying. length '>';
end;
end;
%mend areatag;
/*********************************************************************/
/* MACRO: IMAGEMAP */
/* */
/* DESCRIPTION: */
/* This macro uses a SAS dataset produced by the WEBOUT dataset */
/* option of SAS/GRAPH procedures to write HTML imagemap tags. */
/* */
/* USAGE: %IMAGEMAP(IN, OUT, EXT); */
/* */
/* PARAMETERS: */
/* IN -> WEBOUT dataset */
/* OUT -> HTML output file */
/* NAME -> Optional imagemap name */
/* */
/* NOTES: */
/* This macro requires the AREATAG macro. */
/* */
/* If the optional imagemap name is not given, the imagemap names */
/* are the value of the GRAPH variable in the WEBOUT dataset. */
/* */
/* The optional imagemap name should no be used if the WEBOUT */
/* dataset contains information more than one image as in the case */
/* when by groups used by the procedure that created the WEBOUT */
/* dataset. */
/* */
/* The user is responsible for writing the HTML IMG tag for the */
/* image that uses this imagemap. */
/* */
/*********************************************************************/
%macro imagemap(in, out, name='');
/* Be sure that our NAME= value is 32 characters or less*/
%if %length(&name) > 32
%then %let name = %substr( &name, 1, 32 );
data _null_; set ∈ by graph; file &out mod;
array x{100} x1-x100;
array y{100} y1-y100;
length mapname $ 45;
if first.graph
then do;
if &name = '' then
mapname = '<MAP NAME="' || trim(graph) || '">';
else
mapname = '<MAP NAME="' || &name || '">';
put mapname;
end;
%areatag;
if last.graph then put '</MAP>';
run;
%mend imagemap;
/*********************************************************************/
/* */
/* MACRO: HOTSPOTS */
/* */
/* DESCRIPTION: */
/* This macro uses a SAS dataset produced by the WEBOUT dataset */
/* option of SAS/GRAPH procedures to write an annotate dataset */
/* ofthe areas described in the WEBOUT dataset. */
/* */
/* USAGE: %HOTSPOTS(IN=webout, OUT=annotate, XPIXELS=nx, YPIXELS=ny, */
/* COLOR=name, WIDTH=n, FILL=type */
/* */
/* PARAMETERS: */
/* IN= WEBOUT dataset (default _LAST_) */
/* OUT= Annotate dataset (default HOTSPOTS) */
/* XPIXELS= Number of x pixels in the graph associate with the */
/* WEBOUT dataset (default 1280) */
/* YPIXELS= Number of y pixels in the graph associate with the */
/* WEBOUT dataset (default 1024) */
/* COLOR= Color to be used when drawing the WEBOUT areas */
/* (default RED) */
/* FILL= Fill type to be used when drawing the WEBOUT dataset */
/* areas (default EMPTY) */
/* */
/* NOTES: */
/* Goptions XPIXELS and YPIXELS should be used to insure that the */
/* numbers pixels use in the graph are the same as used with this */
/* macro. */
/* */
/*********************************************************************/
%macro hotspots
(
in=_last_,
out=hotspots,
xpixels=1280,
ypixels=1024,
color=red,
width=1,
fill=empty
);
data &out; set ∈
drop shape length link nxy x1-x100 y1-y100 xscale yscale xmax ymax;
array xarray x1-x100;
array yarray y1-y100;
length function color style $ 16;
retain hsys xsys ysys '3'
color "&color"
style "&fill"
when 'a'
size &width
;
xmax = &xpixels - 1;
ymax = &ypixels - 1;
xscale = 100 / xmax;
yscale = 100 / ymax;
if shape = 'RECT' then do;
x1 = x1 * xscale;
x2 = x2 * xscale;
y1 = (ymax - y1) * yscale;
y2 = (ymax - y2) * yscale;
function = 'poly'; x = x1; y = y1; output;
function = 'polycont'; x = x2; y = y1; output;
function = 'polycont'; x = x2; y = y2; output;
function = 'polycont'; x = x1; y = y2; output;
function = 'polycont'; x = x1; y = y1; output;
end;
if shape = 'POLY' then do;
function = 'poly';
x = x1 * xscale;
y = (ymax - y1) * yscale;
output;
function = 'polycont';
do _i_ = 2 to nxy;
x = xarray * xscale;
y = (ymax - yarray) * yscale;
output;
end;
end;
run;
%mend hotspots;
%macro centroid( in, out, ids, segonly= );
%local lastid pos hasseg tempds;
%let lastid=&ids;
%let pos=%index(&ids,%str( ));
%do %while(&pos > 0);
%let lastid=%substr(&lastid, &pos, %length(&lastid)-&pos+1);
%let pos=%index(&lastid,%str( ));
%end;
data _null_;
segment=.;
set &in(obs=1);
if segment ne . then call symput("hasseg", "true");
run;
data;
set ∈
%if %length(&hasseg) > 0 and %length(&segonly) > 0 %then %do;
where segment = &segonly;
%end;
run;
%let tempds=&SYSLAST;
proc summary data=&tempds;
by &ids;
var x y;
output out=&out min=_xmin _ymin max=_xmax _ymax n=_npoints;
run;
data &out;
set &out;
_xbar = (_xmin+_xmax)*0.5;
_ybar = (_ymin+_ymax)*0.5;
keep &ids _xbar _ybar _npoints;
run;
data &tempds;
retain _newring 1 _found _seglast _xfirst _yfirst _xlast _ylast _yc _xc;
merge &out(in=_want) &tempds;
by &ids;
if _newring then do;
if _want then do;
_xc = _xbar;
_yc = _ybar;
end;
_xfirst = x;
_yfirst = y;
_xlast = .;
_ylast = .;
_seglast= .;
if first.&lastid then _found = 0;
end;
if x = . | y = . then _newring = 1;
else _newring = 0;
_xlast = lag(x);
_ylast = lag(y);
%if %length(&hasseg) > 0 %then %do;
_seglast = lag(segment);
%end;
if ^first.&lastid & _xlast ne . & _ylast ne . then do;
%if %length(&hasseg) > 0 %then %do;
if _seglast = segment then do;
if _newring then do;
x = _xfirst;
y = _yfirst;
end;
link calc;
end;
else if _seglast ne . then do;
_xkeep = x;
_ykeep = y;
x = _xfirst;
y = _yfirst;
segment = _seglast;
link calc;
_xfirst = _xkeep;
_yfirst = _ykeep;
end;
%end;
%else %do;
link calc;
%end;
end;
if last.&lastid then do;
_xlast = x;
_ylast = y;
x = _xfirst;
y = _yfirst;
_newring = 1;
link calc;
if _found = 0 then output;
end;
return;
calc:
/* Swap coordinates */
if _ylast > y then do;
_x1 = _xlast;
_xlast1 = x;
_y1 = _ylast;
_ylast1 = y;
end;
else do;
_x1 = x;
_xlast1 = _xlast;
_y1 = y;
_ylast1 = _ylast;
end;
if _yc >= _ylast1 & _yc < _y1 then do;
_xc = _xlast1 + (_yc - _ylast1)/(_y1 - _ylast1) * (_x1 - _xlast1);
_found = 1;
output;
end;
return;
keep _xc _yc &ids;
run;
proc sort data=&tempds;
by &ids _xc;
run;
data &out;
retain _xc1 . _dist1 _dist _xckeep 0;
set &tempds;
by &ids;
if _xc1 = . then
_xc1 = _xc;
else do;
_dist1 = abs(_xc-_xc1);
if _dist1 > _dist then do;
_xckeep = (_xc+_xc1)/2;
_dist = _dist1;
end;
_xc1 = .;
end;
if last.&lastid then do;
if first.&lastid then x = _xc;
else x = _xckeep;
y = _yc;
output;
_dist= 0;
_xc1 = .;
end;
keep x y &ids;
run;
%mend;
/*********************************************************************/
/* */
/* MACRO: MAPLABEL */
/* */
/* DESCRIPTION: */
/* This macro is used to create an annotate data set for use with */
/* PROC GMAP output. The resulting data set can be used with ANNO=*/
/* The user can use the default font/size information, or choose */
/* their own. */
/* */
/* USAGE: %HOTSPOTS(<map-ds>, <attribute-ds>, <output-ds>,<var>, */
/* <ids>, FONT=, COLOR=, SIZE=, HSYS=); */
/* */
/* PARAMETERS: */
/* <map-ds> Input Map data set */
/* <attr-ds> Attribute data set that contains var for label */
/* <out-ds> Resulting output data set for use in ANNO= in GMAP */
/* <var> Variable for label on <attr-ds>. Can be text or num */
/* <ids> Space-separated list of IDs that the map and attr */
/* data sets are sorted on. */
/* FONT= Font for the label. Default is SWISS. */
/* COLOR= Color of the label. Devault is BLACK. */
/* SIZE= Size of the label. Default is 1 <unit> */
/* HSYS= UNIT system for SIZE=. Default is 3 (PERCENT) */
/* SEGONLY= Only process the segment specified of each polygon */
/* set (map area). Useful to not have centroid placed */
/* in non-polygon area */
/* */
/* NOTES: */
/* */
/*********************************************************************/
%macro maplabel(mapds,attrds,outds,textvar,ids,
font=swiss,color=black,size=2,hsys=3,segonly=);
%local tempds;
%centroid(&mapds,&outds,&ids,segonly=&segonly);
data;
set &attrds;
run;
%let tempds=&SYSLAST;
proc sort data=&tempds;
by &ids;
run;
data &outds;
length position xsys ysys when position hsys $1 text $40;
retain function 'label'
xsys ysys '2'
hsys "&hsys"
when 'a'
position '5'
style "&font"
color "&color"
size &size;
merge &outds(in=want) &tempds(keep=&textvar &ids);
by &ids;
if vtype(&textvar) = 'C' then
text=&textvar;
else
text=left(input(&textvar,BEST.));
if want then output;
run;
proc sort data=&outds nodupkey;by &ids; run;
%mend;
%macro maplabel(south_korea,south_korea_attr,maggie,ID1NAME,ID1 ID,
font=swiss,color=black,size=2,hsys=3,segonly=);
... View more