*! NJC 1.1.1 23 Sept 2004 * NJC 1.1.0 19 Sept 2004 * NJC 1.0.0 6 Sept 2004 *! -gr3- wwg STB-12 program scat3 version 8 // set defaults Defaults // syntax check syntax varlist(min=3 max=3) [if] [in] [ , /// Rotate(int `rotate') Elevate(int `elevate') /// axistype(string) shadow SHADOW2(passthru) /// titlex(str asis) titley(str asis) titlez(str asis) /// variablenames SEParate(passthru) * ] marksample touse qui count if `touse' if r(N) == 0 error 2000 // axistype choice local at "`axistype'" if "`at'" == "" local axistype "`axis'" else { local badaxis 1 foreach c in minimum zero outside table { if "`at'" == substr("`c'", 1, length("`at'")) { local badaxis 0 local axistype "`c'" } } if `badaxis' { di as err "invalid axis type `axistype'" exit 198 } } // prepare dataset if _N < 9 { preserve set obs 9 } quietly { tokenize "x y z" local i = 1 // variables rescaled: minimum 0, maximum 1 foreach v of local varlist { su `v' if `touse', meanonly local range = r(max) - r(min) if `range' == 0 local range 1 tempvar ``i'' gen ```i''' = (`v' - r(min)) / `range' local ``i''zero = -r(min) / `range' local ++i } // set up axes /* axis information: one of: table outside zero minimum axis == table adds "table-top" axis to the data. adds to data: x y z 1 1 1 0 2 0 1 0 3 0 0 0 4 0 0 1 5 1 0 1 6 1 0 0 7 0 0 0 8 1 0 0 9 1 1 0 axis == outside adds "outside" axis to data. adds to data: x y z 1 1 1 0 2 0 1 0 3 0 0 0 4 0 0 1 axis == zero adds an axis meeting at (0,0,0) to the data. adds to data: x y z 1 0 . . 2 . . . 3 . . 1 4 . . 0 5 . . . 6 . 0 . 7 . 1 . 8 . . . 9 1 . . The missings are converted to the scaled number corresponding to zero (xzero yzero zzero). axis == minimum adds an axis centred on the minimum of the data. adds to data: x y z 1 0 1 0 2 0 0 0 3 0 0 1 4 0 0 0 5 1 0 0 */ tempvar xaxis yaxis zaxis if "`axistype'" == "table" { gen `xaxis' = 1 if inlist(_n, 1, 5, 6, 8, 9) replace `xaxis' = 0 if inlist(_n, 2, 3, 4, 7) gen `yaxis' = 1 if inlist(_n, 1, 2, 9) replace `yaxis' = 0 in 3/8 gen `zaxis' = 0 in 1/9 replace `zaxis' = 1 in 4/5 } else if "`axistype'" == "outside" { gen `xaxis' = _n == 1 in 1/4 gen `yaxis' = _n <= 2 in 1/4 gen `zaxis' = _n == 4 in 1/4 } else if "`axistype'" == "zero" { gen `xaxis' = /// cond(_n == 1,0,cond(_n == 9,1,`xzero')) in 1/9 gen `yaxis' = /// cond(_n == 6,0,cond(_n == 7,1,`yzero')) in 1/9 gen `zaxis' = /// cond(_n == 3,1,cond(_n == 4,0,`zzero')) in 1/9 } else if "`axistype'" == "minimum" { gen `xaxis' = cond(_n == 5,1,0) in 1/5 gen `yaxis' = cond(_n == 1,1,0) in 1/5 gen `zaxis' = cond(_n == 3,1,0) in 1/5 } // add titles (by default variable labels) to data tempvar title xtitle ytitle ztitle foreach v in x y z { parse `"`title`v''"', parse(",") if `"`1'"' != "" & `"`1'"' != "," { local text`v' `1' local title`v' `"`3'"' } else if "`1'" == "," { local title`v' "`2'" } } tokenize `varlist' gen `title' = `"`textx'"' in 1 if mi(`title'[1]) { if "`variablenames'" == "" { replace `title' = `"`: var label `1''"' in 1 } if mi(`title'[1]) replace `title' = "`1'" in 1 } replace `title' = `"`texty'"' in 2 if mi(`title'[2]) { if "`variablenames'" == "" { replace `title' = `"`: var label `2''"' in 2 } if mi(`title'[2]) replace `title' = "`2'" in 2 } replace `title' = `"`textz'"' in 3 if mi(`title'[3]) { if "`variablenames'" == "" { replace `title' = `"`: var label `3''"' in 3 } if mi(`title'[3]) replace `title' = "`3'" in 3 } gen `xtitle' = cond(_n == 1,.5,-.1) in 1/3 gen `ytitle' = cond(_n == 1,1.1,cond(_n == 2,.5,0)) in 1/3 gen `ztitle' = cond(_n == 3,.5,0) in 1/3 // convert the angles into radians, store as scalars `SC*' tempname SC1 SC2 SC3 SC4 SC5 SC6 SC7 SC8 SC9 scalar `SC1' = (360 - `rotate') * _pi/180 scalar `SC2' = (270 - `elevate') * _pi/180 scalar `SC3' = `tilt' * _pi/180 scalar `SC4' = sin(`SC1') scalar `SC5' = cos(`SC1') scalar `SC6' = sin(`SC2') scalar `SC7' = cos(`SC2') scalar `SC8' = sin(`SC3') scalar `SC9' = cos(`SC3') tempvar newy newytitle newyaxis tempvar vybase vy vyaxis vytitle vx vxaxis vxtitle // rotate about z-axis (rotation) gen `newy' = `x' * `SC4' + `y' * `SC5' gen `newyaxis' = `xaxis' * `SC4' + `yaxis' * `SC5' gen `newytitle' = `xtitle' * `SC4' + `ytitle' * `SC5' // rotate about x-axis (elevation) and y-axis (tilt) gen `vybase' = `newy' * `SC7' gen `vy' = `vybase' - `z' * `SC6' gen `vyaxis' = (`newyaxis' * `SC7') - `zaxis' * `SC6' gen `vytitle' = (`newytitle' * `SC7') - `ztitle' * `SC6' gen `vx' = (`x' * `SC5' - `y' * `SC4') * /// `SC9' + (`newy' * `SC6' + `z' * `SC7') * `SC8' gen `vxaxis' = (`xaxis' * `SC5' - `yaxis' * `SC4') * /// `SC9' + (`newyaxis' * `SC6' + `zaxis' * `SC7') * `SC8' gen `vxtitle' = (`xtitle' * `SC5' - `ytitle' * `SC4') * /// `SC9' + (`newytitle' * `SC6' + `ztitle' * `SC7') * `SC8' drop `x' `y' `z' drop `xaxis' `yaxis' `zaxis' drop `xtitle' `ytitle' `ztitle' drop `newy' `newytitle' `newyaxis' } local vars "`touse' `vx' `vy' `vybase' `vxaxis' `vyaxis'" local vars "`vars' `vxtitle' `vytitle' `title'" Show `vars', rot(`rotate') elev(`elevate') `shadow' `shadow2' /// titlex(`titlex') titley(`titley') titlez(`titlez') `separate' `options' end program Show version 8 syntax varlist [ , /// axes(str asis) spikes(str asis) /// titlex(str asis) titley(str asis) titlez(str asis) /// shadow shadow2(str asis) Rot(int 999) Elev(int 999) separate(varname) * ] tokenize `varlist' args touse vx vy vybase vxaxis vyaxis vxtitle vytitle title local VY "`vy'" qui if "`separate'" != "" { separate `vy', by(`separate') shortlabel local vy "`r(varlist)'" foreach v of local vy { local label : variable label `v' local label = substr(`"`label'"', index(`"`label'"',"==") + 2, .) label var `v' `"`label'"' } numlist "6/`= 5 + `: word count `vy'''" local legend "legend(order(`r(numlist)'))" } else local legend "legend(off)" di as txt "note: projecting at rotate(" as res "`rot'" /// as txt ") elevate(" as res "`elev'" as txt ")" if "`shadow'`shadow2'" != "" { twoway scatter `vybase' `vx' if `touse', msize(*0.5) `shadow2' || /// line `vyaxis' `vxaxis', clp(solid) `axes' || /// scatter `vytitle' `vxtitle' in 1, /// ms(none) mlabel(`title') mlabp(0) mlabc(black) `titlex' || /// scatter `vytitle' `vxtitle' in 2, /// ms(none) mlabel(`title') mlabp(0) mlabc(black) `titley' || /// scatter `vytitle' `vxtitle' in 3, /// ms(none) mlabel(`title') mlabang(vertical) mlabp(0) mlabc(black) `titlez' || /// scatter `vy' `vx' if `touse', /// plotregion(style(none)) yla(, nogrid) xla(, nogrid) /// yscale(r(.,.) off) xscale(r(.,.) off) `legend' `options' } else twoway rspike `VY' `vybase' `vx' if `touse', `spikes' || /// line `vyaxis' `vxaxis', clp(solid) `axes' || /// scatter `vytitle' `vxtitle' in 1, /// ms(none) mlabel(`title') mlabp(0) mlabc(black) `titlex' || /// scatter `vytitle' `vxtitle' in 2, /// ms(none) mlabel(`title') mlabp(0) mlabc(black) `titley' || /// scatter `vytitle' `vxtitle' in 3, /// ms(none) mlabel(`title') mlabang(vertical) mlabp(0) mlabc(black) `titlez' || /// scatter `vy' `vx' if `touse', /// plotregion(style(none)) yla(, nogrid) xla(, nogrid) /// yscale(r(.,.) off) xscale(r(.,.) off) `legend' `options' end program Defaults version 8 c_local rotate 45 c_local elevate 45 c_local tilt 0 c_local axis "table" end