*! -spmap_polygon-: Auxiliary program for -spmap- *! Version 1.3.1 - 09 January 2018 - StataCorp edit for stroke align *! Version 1.3.0 - 13 March 2017 *! Version 1.2.0 - 14 March 2008 *! Version 1.1.0 - 7 May 2007 *! Version 1.0.0 - 7 December 2006 *! Author: Maurizio Pisati *! Department of Sociology and Social Research *! University of Milano Bicocca (Italy) *! maurizio.pisati@unimib.it * ---------------------------------------------------------------------------- * 1. Define program * ---------------------------------------------------------------------------- program spmap_polygon, rclass version 9.2 * ---------------------------------------------------------------------------- * 2. Define syntax * ---------------------------------------------------------------------------- syntax, [Data(string)] /// [Select(string asis)] /// [BY(string)] /// /// [FColor(string asis)] /// [OColor(string asis)] /// [OSize(string)] /// [OPattern(string)] /// 1.3.0 [OAlign(string)] /// /// [LEGENDA(string)] /// [LEGTitle(string asis)] /// [LEGLabel(string)] /// [LEGShow(string)] /// [LEGCount] * ---------------------------------------------------------------------------- * 3. Check syntax * ---------------------------------------------------------------------------- /* Preserve data */ preserve /* Check and open dataset */ if ("`data'" == "") { di as err "{p}Problem with option {bf:{ul:pol}ygon()}: suboption " /// "{bf:{ul:d}ata()} is required{p_end}" exit 198 } if (substr(reverse("`data'"),1,4) != "atd.") { local data "`data'.dta" } capture confirm file "`data'" if _rc { di as err "{p}Problem with option {bf:{ul:pol}ygon()}: file " /// "{bf:`data'} specified in suboption {bf:{ul:d}ata()} " /// "not found{p_end}" exit 601 } use "`data'", clear cap confirm numeric variable _ID _X _Y if _rc { di as err "{p}Problem with option {bf:{ul:pol}ygon()}: file " /// "{bf:`data'} specified in suboption {bf:{ul:d}ata()} " /// "is not a valid {help spmap##sd_polygon:{it:polygon}} " /// "dataset {p_end}" exit 198 } /* Select relevant records */ if (`"`select'"' != "") { cap `select' if _rc { di as err "{p}Problem with option {bf:{ul:pol}ygon()}: suboption " /// "{bf:{ul:s}elect()} specified incorrectly{p_end}" exit 198 } } /* Check option by() */ if ("`by'" != "") { cap unab by : `by' if (_rc == 111) { di as err "{p}Problem with option {bf:{ul:pol}ygon()}: " /// "variable {bf:`by'} specified in suboption " /// "{bf:{ul:by}()} not found{p_end}" exit 111 } if (_rc == 198) { di as err "{p}Problem with option {bf:{ul:pol}ygon()}: " /// "string {bf:`by'} specified in suboption " /// "{bf:{ul:by}()} is not a valid variable " /// "name{p_end}" exit 198 } local NW : word count `by' if (`NW' > 1) { di as err "{p}Problem with option {bf:{ul:pol}ygon()}: " /// "suboption {bf:{ul:by}()} accepts only one " /// "variable{p_end}" exit 198 } } /* Check option legenda() */ if ("`legenda'" != "") { local LIST "on off" local EXIST : list posof "`legenda'" in LIST if !`EXIST' { di as err "{p}Problem with option {bf:{ul:pol}ygon()}: " /// "suboption {bf:{ul:legenda}()} accepts only one " /// "of the following keywords: {bf:`LIST'}{p_end}" exit 198 } } /* Check options relevant only when legenda(on) */ if ("`legenda'" == "on") { /* Check option leglabel() */ if (`"`leglabel'"' == "") & ("`by'" == "") { di as err "{p}Problem with option {bf:{ul:pol}ygon()}: since " /// "you have specified suboption {bf:{ul:legenda}(on)} " /// "but you have not specified any group variable in " /// "suboption {bf:{ul:by}()}, you are requested to " /// "specify suboption {bf:{ul:legl}abel()}{p_end}" exit 198 } /* Check option legshow() */ if ("`legshow'" != "") { cap numlist "`legshow'" if _rc { di as err "{p}Problem with option {bf:{ul:pol}ygon()}: " /// "invalid numlist in suboption " /// "{bf:{ul:legs}how()}{p_end}" exit 121 } } /* End */ } /* Marksample */ marksample TOUSE if ("`by'" != "") markout `TOUSE' `by', strok qui count if `TOUSE' if (r(N) == 0) error 2000 * ---------------------------------------------------------------------------- * 4. Define basic objects * ---------------------------------------------------------------------------- /* Select relevant records */ qui keep if `TOUSE' /* Set default fill color */ local fcolor_d "none" if (`"`fcolor'"' == "") local fcolor "`fcolor_d' ..." /* Set default outline color */ local ocolor_d "black" if (`"`ocolor'"' == "") local ocolor "`ocolor_d' ..." /* Set default outline thickness */ local osize_d "thin" if ("`osize'" == "") local osize "`osize_d' ..." /* Set default outline pattern */ local opattern_d "solid" if ("`opattern'" == "") local opattern "`opattern_d' ..." /* Set default outline alignment */ local oalign_d "center" if ("`oalign'" == "") local oalign "`oalign_d' ..." /* Set default legend */ if ("`legenda'" == "") local legenda "off" /* Set legend title when legtitle(varlab) */ if ("`legenda'" == "on") & ("`by'" != "") & (`"`legtitle'"' == "varlab") { local legtitle : variable label `by' if (`"`legtitle'"' == "") local legtitle "`by'" } * ---------------------------------------------------------------------------- * 5. Create working dataset * ---------------------------------------------------------------------------- /* Housekeeping */ cap drop __POL* /* Generate group variable */ if ("`by'" == "") qui gen __POL_G = 1 if ("`by'" != "") qui egen __POL_G = group(`by'), lname(__POL_G) qui tab __POL_G local NG = r(r) /* Generate coordinate variables */ qui gen __POL_X = _X qui gen __POL_Y = _Y /* Count objects */ if ("`legenda'" == "on") & ("`legcount'" != "") { forval i = 1/`NG' { qui tab _ID if __POL_G == `i' local COUNT "`COUNT'`r(r)' " } } /* Save dataset */ keep __POL* qui save "__POL.dta", replace * ---------------------------------------------------------------------------- * 6. Parse style lists * ---------------------------------------------------------------------------- /* Set list of available color palettes */ local PALETTE "`PALETTE' Accent Blues BrBG BuGn BuPu Dark2 GnBu Greens Greys" local PALETTE "`PALETTE' OrRd Oranges PRGn Paired Pastel1 Pastel2 PiYG PuBu" local PALETTE "`PALETTE' PuBuGn PuOr PuRd Purples RdBu RdGy RdPu RdYlBu" local PALETTE "`PALETTE' RdYlGn Reds Set1 Set2 Set3 Spectral YlGn YlGnBu" local PALETTE "`PALETTE' YlOrBr YlOrRd" local PALETTE "`PALETTE' BuRd BuYlRd Heat Terrain Topological" local PALETTE "`PALETTE' Blues2 Greens2 Greys2 Reds2 Rainbow" /* Parse option fcolor() */ local EXIST : list posof `"`fcolor'"' in PALETTE if `EXIST' { if (`NG' > 1) { spmap_color "`fcolor'" `NG' local fcolor `"`s(colors)'"' } else { di as err "{p}Problem with option {bf:{ul:pol}ygon()}: " /// "when no group variable is specified in suboption " /// "{bf:{ul:by}()}, suboption {bf:{ul:fc}olor()} " /// "does not accept palette names{p_end}" exit 198 } } else { spmap_psl, l(`fcolor') m(`NG') o({bf:{ul:fc}olor()}) d(`fcolor_d') local fcolor `"`s(pl)'"' } /* Parse option ocolor() */ local EXIST : list posof `"`ocolor'"' in PALETTE if `EXIST' { if (`NG' > 1) { spmap_color "`ocolor'" `NG' local ocolor `"`s(colors)'"' } else { di as err "{p}Problem with option {bf:{ul:pol}ygon()}: " /// "when no group variable is specified in suboption " /// "{bf:{ul:by}()}, suboption {bf:{ul:oc}olor()} " /// "does not accept palette names{p_end}" exit 198 } } else { spmap_psl, l(`ocolor') m(`NG') o({bf:{ul:oc}olor()}) d(`ocolor_d') local ocolor `"`s(pl)'"' } /* Parse option osize() */ spmap_psl, l(`osize') m(`NG') o({bf:{ul:os}ize()}) d(`osize_d') local osize `"`s(pl)'"' /* Parse option opattern() */ spmap_psl, l(`opattern') m(`NG') o({bf:{ul:op}attern()}) d(`opattern_d') local opattern `"`s(pl)'"' /* Parse option oalign() */ spmap_psl, l(`oalign') m(`NG') o({bf:{ul:op}attern()}) d(`oalign_d') local oalign `"`s(pl)'"' * ---------------------------------------------------------------------------- * 7. Compose command * ---------------------------------------------------------------------------- /* Compose command */ forval i = 1/`NG' { local FC : word `i' of `fcolor' local OC : word `i' of `ocolor' if ("`OC'" == "none") local OC "`FC'" local OS : word `i' of `osize' local OP : word `i' of `opattern' local OA : word `i' of `oalign' if c(stata_version) >= 15 { local LA `"la("`OA'")"' } local GRAPH `"`GRAPH'(area __POL_Y __POL_X if __POL_G == `i', nodropbase"' local GRAPH `"`GRAPH' cmissing(n) fc("`FC'") fi(100) lc("`OC'")"' local GRAPH `"`GRAPH' lw("`OS'") lp("`OP'") `LA') "' } * ---------------------------------------------------------------------------- * 8. Set legend order and labels * ---------------------------------------------------------------------------- /* Set number of keys */ local NK = `NG' /* legenda(off) */ if ("`legenda'" == "off") { local TITLE "" local KEY "" local LABEL "" } /* legenda(on) & by == "" */ if ("`legenda'" == "on") & ("`by'" == "") { /* Title */ if (`"`legtitle'"' != "") { local Q = strpos(`"`legtitle'"',`"""') /* " */ if (`Q' == 0) local TITLE `"- "`legtitle'""' else local TITLE `"- `legtitle'"' } else { local TITLE "" } /* Keys */ local KEY "1 " /* Labels */ if ("`legcount'" == "") { local LABEL `"`"`leglabel'"' "' } else { local OBS : word 1 of `COUNT' local LABEL `"`"`leglabel' (`OBS')"' "' } /* End */ } /* legenda(on) & by == !" */ if ("`legenda'" == "on") & ("`by'" != "") { /* Title */ if (`"`legtitle'"' != "") { local Q = strpos(`"`legtitle'"',`"""') /* " */ if (`Q' == 0) local TITLE `"- "`legtitle'""' else local TITLE `"- `legtitle'"' } else { local TITLE "" } /* Keys */ if ("`legshow'" == "") { numlist "1/`NK'" local KEY "`r(numlist)'" } else { qui levelsof __POL_G, local (VL) local CHECK : list legshow in VL if !`CHECK' { di as err "{p}Problem with option {bf:{ul:pol}ygon()}: " /// "one or more keys specified in suboption " /// "{bf:{ul:legs}how()} do not exist. Valid keys " /// " are: `VL'{p_end}" exit 198 } else local KEY "`legshow'" } /* Labels */ foreach K in `KEY' { local LBL : label (__POL_G) `K' if ("`legcount'" == "") { local LABEL `"`LABEL'`"`LBL'"' "' } else { local OBS : word `K' of `COUNT' local LABEL `"`LABEL'`"`LBL' (`OBS')"' "' } } /* End */ } * ---------------------------------------------------------------------------- * 9. Return info of interest * ---------------------------------------------------------------------------- /* Return command */ return local command `"`GRAPH'"' /* Return min/max coordinates */ qui summ __POL_X return local xmin = r(min) return local xmax = r(max) qui summ __POL_Y return local ymin = r(min) return local ymax = r(max) /* Return legend info */ return local title `"`TITLE'"' return local key `"`KEY'"' return local label `"`LABEL'"' return local nk = `NK' * ---------------------------------------------------------------------------- * 10. End program * ---------------------------------------------------------------------------- restore end