/*
Program creates column or row percentages of a two-way tabulation and saves results in a specified matrix with appropriate labels.

Version 1.0
July 2016
Loris Fagioli
lfagioli@ivc.edu
*/
program rcolp2mat
version 10
syntax varlist(max=2) [if/] [in] [fweight aweight], matrix(string) [row] [col] [detail] [total] [missing]

if "`row'"=="" & "`col'"=="" {
			di as err "row or col option required"
			exit 198
			}
if "`row'"=="row" & "`col'"=="col" {
			di as err "only one option (row or col) allowed"
			exit 198
			}
if "`detail'"=="detail" & "`total'"=="total" {
			di as err "only one option (detail or total) allowed"
			exit 198
			}

qui {

if "`if'"!="" local iff "if `if'"
if "`if'"!="" local iff2 "& `if'"
local varname1: word 1 of `varlist'
local varname2: word 2 of `varlist'

tab `varlist' `iff' `in' [`weight' `exp'], matcell(`matrix') `missing'
if "`row'"=="row"  mata: st_matrix("`matrix'", (st_matrix("`matrix'")  :/ rowsum(st_matrix("`matrix'"))))
if "`col'"=="col"  mata: st_matrix("`matrix'", (st_matrix("`matrix'")  :/ colsum(st_matrix("`matrix'"))))


*Add labels
levelsof `varname1' if missing(`varname2')==0 `iff2' `in', local(a) `missing'
levelsof `varname2' if missing(`varname1')==0 `iff2' `in', local(b) `missing'


local i=1
foreach r of local a {
capture local rr: label (`varname1') `r'
if _rc!=0 local rr `r'
local rr=ustrregexra("`rr'"," ","_") //if label has spaces
local rr=ustrregexra("`rr'","/","_") //if label has slashes
matrcrename `matrix' row `i' "`rr'"
local ++i
}

local i=1
foreach c of local b {
capture local cc: label (`varname2') `c'
if _rc!=0 local cc `c'
local cc=ustrregexra("`cc'"," ","_") //if label has spaces
local cc=ustrregexra("`cc'","/","_") //if label has slashes
matrcrename `matrix' col `i' "`cc'"
local ++i
}

*Add detail
if "`detail'"!="" {


		tab `varname1' if missing(`varname2')==0 `iff2' `in' [`weight' `exp'], matcell(r) 
		matrix colnames r="Total N"
		matrix `matrix'=`matrix',r
		tab `varname2' if missing(`varname1')==0 `iff2' `in' [`weight' `exp'], matcell(c) 
		matrix a=r(N)
		matrix c=c'
		matrix c=c,a
		matrix rownames c="Total N"
		matrix `matrix'=`matrix'\c

		matrix drop a c r
		
}


if "`total'"!="" {

if "`row'"=="row" {
		tab `varname2' if missing(`varname1')==0 `iff2' `in' [`weight' `exp'], matcell(c) `missing'
		matrix c=c'
		mata: st_matrix("c", (st_matrix("c")  :/ rowsum(st_matrix("c"))))
		matrix rownames c="Total %"
		matrix `matrix'=`matrix'\c
		matrix drop c 

}


if "`col'"=="col" {
		tab `varname1' if missing(`varname2')==0 `iff2' `in' [`weight' `exp'], matcell(c) `missing'
		mata: st_matrix("c", (st_matrix("c")  :/ colsum(st_matrix("c"))))
		matrix colnames c="Total %"
		matrix `matrix'=`matrix',c
		matrix drop c 
}
}

}

matrix li `matrix'
end 	

*-------------------------------------------------------------------------
*Subroutine by Nick Cox from STATA listserv: http://www.stata.com/statalist/archive/2006-11/msg00537.html
*-------------------------------------------------------------------------

program matrcrename 
	version 8 
	// syntax matrixname row_or_col which_row_or_col new_name 

	// matrix name 
	gettoken matrix 0 : 0 
	confirm matrix `matrix' 

	// row or column 
	gettoken which 0 : 0 
	local length = length("`which'") 
	if lower("`which'") == substr("row",1,`length') { 
		local which row 
	}
	else if lower("`which'") == substr("column",1,`length') { 
		local which col
	}
	else { 
		di as err "second argument should specify row or column" 
		exit 198 
	} 

	// which row or column 
	gettoken where newname : 0 
	if "`which'" == "row" { 
		capture local found = inrange(`where', 1, rowsof(`matrix'))
		if _rc { 
			di as err "inappropriate row number?"
			exit 498 
		} 
		if !`found' { 
			di as err "row out of range" 
			exit 498 
		}	
	}	
	else { 
		capture local found = inrange(`where', 1, colsof(`matrix')) 
		if _rc { 
			di as err "inappropriate column number?"
			exit 498 
		} 
		if !`found' { 
			di as err "column out of range" 
			exit 498 
		}	
	} 

	// test newname 
	tempname moo 
	matrix `moo' = J(1,1,1) 
	capture matrix rownames `moo' = `newname' 
	if _rc { 
		local what = cond("`which'" == "col", "column", "row") 
		di as err "inappropriate `what' name?" 
		exit 498
	} 

	// in business! 
	local names : `which'names `matrix' 
	tokenize `names'
	local `where' `newname'
	local newnames "`*'" 
	matrix `which'names `matrix' = `newnames' 
end