fix rename bernie

fix rename bernie

* 1 billion divided equally between states
* 1 billion distributed on the basis of relative 16-25 y/o compared to total in all states
* 1 billion on relative unemployed compared to toal in all states
* 1 billion on the basis of the rleative # disadvantaged youth compared to total in all states

*STEPS:
* # of 16-25 y/o's per state
* total # of 16-25 y/os
* # of unemployed per state
* total # unemployed
* # disdvantaged youth
* total # disadvantaged youth

*then by puma w/in state
*
*tabulate age if statefip == 06 & puma == 3703 [fweight=perwt]
use "/Users/braddv/Desktop/BERNIE/employamericansnow/bernie17.dta", clear

drop if year == 2013
drop if gq == 4 | gq == 3

gen youth = (age <= 24 & age >= 16)
gen povline = 11670 + (famsize-1)*4060
gen disadvantaged = (ftotinc < povline)
gen unemployed = (empstat == 2)
gen notemployed = (empstat != 1)
gen unemployed_youth = youth * unemployed
gen notemployed_youth = youth * notemployed
gen disadvantaged_youth = youth * disadvantaged

egen youth_in_hh = max(youth), by(serial)
egen unemployed_in_hh = max(unemployed), by(serial)
egen disadvantaged_hh = max(disadvantaged), by(serial)

egen youth_in_fam = max(youth), by(serial famunit)
egen unemployed_in_fam = max(unemployed), by(serial famunit)
egen disadvantaged_fam = max(disadvantaged), by(serial famunit)
egen disadvantagedyouth_fam = max(disadvantaged_youth), by(serial famunit)
egen unemployedyouth_fam = max(unemployed_youth), by(serial famunit)
egen notemployedyouth_fam = max(notemployed_youth), by(serial famunit)

egen youth_state = total(perwt * youth), by(statefip)
egen youth_puma = total(perwt * youth), by(statefip puma)
*sum youth_puma if statefip == 06 & puma == 3703
*25371 youth in lancaster
gen youth_percentage = youth_puma / youth_state

egen unemployed_state = total(perwt * unemployed), by(statefip)
egen unemployed_puma = total(perwt * unemployed), by(statefip puma)

gen unemployed_percentage = unemployed_puma / unemployed_state

egen unemployed_youth_state = total(perwt * unemployedyouth), by(statefip)

*sum youth_puma if statefip == 06 & puma == 3703
*5797 youth in lancaster

egen disadvantaged_state = total(perwt * disadvantaged_youth), by(statefip)
egen disadvantaged_puma = total(perwt * disadvantaged_youth), by(statefip puma)

gen disadvantaged_percentage = disadvantaged_puma / disadvantaged_state

egen youth_total = total(perwt * youth)
egen unemployed_total = total(perwt * unemployed)
egen disadvantaged_total = total(perwt * disadvantaged_youth)

gen youth_percentage_state = youth_state/youth_total
gen unemployed_percentage_state = unemployed_state/unemployed_total
gen disadvantaged_percentage_state = disadvantaged_state/disadvantaged_total

gen state_money = 1000 * .02 + 1000 * youth_percentage_state + 1000 * unemployed_percentage_state + 1000 * disadvantaged_percentage_state
gen state_money2 = 1333 * youth_percentage_state + 1333 * unemployed_percentage_state + 1333 * disadvantaged_percentage_state

egen npumas = nvals(puma), by(statefip)

gen puma_money = (state_money/3) * (youth_percentage + unemployed_percentage + disadvantaged_percentage)
gen puma_money2 = (state_money2/3) * (youth_percentage + unemployed_percentage + disadvantaged_percentage)

gen minwage = 7.25
replace minwage = 8.75 if statefip == 02
replace minwage = 8.05 if statefip == 04
replace minwage = 7.5 if statefip == 05
replace minwage = 9 if statefip == 06
replace minwage = 8.14 if statefip == 08
replace minwage = 9.15 if statefip == 09
replace minwage = 8.25 if statefip == 10
replace minwage = 10.5 if statefip == 11
replace minwage = 8.05 if statefip == 12
replace minwage = 8.25 if statefip == 17
replace minwage = 7.5 if statefip == 23
replace minwage = 8.25 if statefip == 26
replace minwage = 9 if statefip == 25
replace minwage = 7.65 if statefip == 29
replace minwage = 8.05 if statefip == 30
replace minwage = 8 if statefip == 31
replace minwage = 8.25 if statefip == 32
replace minwage = 8.38 if statefip == 34
replace minwage = 7.5 if statefip == 35
replace minwage = 8.75 if statefip == 36
replace minwage = 8.15 if statefip == 39
replace minwage = 9.25 if statefip == 41
replace minwage = 9 if statefip == 44
replace minwage = 8.5 if statefip == 46
replace minwage = 9.15 if statefip == 50
replace minwage = 9.47 if statefip == 53
replace minwage = 8 if statefip == 54

gen millionperyr = minwage * .001 //assuming work 1000 hrs per yr

gen numjobspuma = puma_money / millionperyr //.0105 is a 10,500 dollar per yr job ($15*30hrs*12weeks in summer and $15*10hrs*34weeks in schoolyr)
gen numjobspuma2 = puma_money2 / millionperyr
//alternatively, could be doled out as 48 weeks of $15/hr pay 15 hrs a week
gen numjobsstate = state_money / millionperyr
gen numjobsstate2 = state_money2 / millionperyr

*gen numjobspumamin = puma_money / state_minwage
*gen numjobsstatemin = state_money / state_minwage

*figure out households w/ youth in them
egen householdwithyouth = max(youth), by(serial)
*youth hh's living in poverty
gen youthinpov = (householdwithyouth & (poverty <= 100) & pernum == 1)

egen familyheadnum = min(pernum), by(serial famunit)
gen familyhead = (familyheadnum == pernum)
gen familyheadyouth = familyhead*youth_in_fam
gen familyheadyouthunemployed = familyhead*unemployedyouth_fam
gen familyheadyouthnotemployed = familyhead*notemployedyouth_fam
gen familyheadyouthdisadvantaged = familyhead*disadvantagedyouth_fam
gen familyheadydandnotemp = familyheadyouthnotemployed*familyheadyouthdisadvantaged

egen finccut = cut(ftotinc), at(0,5000,10000,25000,50000,100000,250000,2000000) icodes

histogram finccut if familyheadyouth [fweight=perwt], discrete

gen hisp = hispan != 0

gen single = marst != 1

gen employed = empstat == 1

gen inschool = gradeatt > 0

gen racef = 1 if racesing == 1 & hisp == 0
replace racef = 2 if racesing == 2 & hisp == 0
replace racef = 3 if hisp
replace racef = 4 if racesing > 2 & hisp == 0

gen coleduc = 0 if educ <= 5
replace coleduc = 1 if educ == 6
replace coleduc = 2 if educ > 6 & educ < 9
replace coleduc = 3 if educ >= 9

gen rural = (metro == 0 | metro == 1)

probit employed i.coleduc i.single i.racef i.finccut i.sex i.rural i.statefip i.inschool if youth [fweight=perwt]
predict employedp
gen modelemployed = employedp > .5
gen correctmodel = modelemployed == employed
tab correctmodel if youth [fweight=perwt]

egen youthempprob = max(employedp) if youth, by(serial famunit)
egen headmaxyouthempp = max(youthempprob), by(serial famunit)
gen invheadmaxyouthempp = 1-headmaxyouthempp if !missing(headmaxyouthempp)
gen invyouthempprob = 1-youthempprob if !missing(youthempprob)

save "/Users/braddv/Desktop/BERNIE/employamericansnow/bernie17egen.dta", replace

error: pathspec 'bernie.do' did not match any file(s) known to git


stata script to write 'conditional use' tables

- Makes tables that tell what percentage of users use a certain tool,
given that they also use another tool.
- Can compare all tools from two phases (eg, 'writing' and 'analysis')

use 101innov.dta", clear

local phase_row analysis
local phase_col write

qui ds tool_`phase_row'_*, has(type byte)
local vlist_row `r(varlist)'
qui ds tool_`phase_col'_*, has(type byte)
local vlist_col `r(varlist)'

local llr=wordcount("`vlist_row'")
local llc=wordcount("`vlist_col'")

//set trace on
set tracedepth 1
mata: T=J(`llr',`llc',.);
local Lr=length("tool_`phase_row'_")+1
local Lc=length("tool_`phase_col'_")+1
local rownames ""
local colnames ""
local ii 0
forval row=1/`llr'	{
	local n=substr("`: word `row' of `vlist_row''",`Lr',.)
	local rownames `rownames' `n'
//	macro list _rownames
	local `++ii'
	forval col=1/`llc'	{
		if `ii'==`col'	{
			local n=substr("`: word `col' of `vlist_col''",`Lc',.)
			local colnames `colnames' `n'
//			macro list _colnames
		}
		summ `: word `col' of `vlist_col'' if `: word `row' of `vlist_row''==1, mean
		scalar p=r(mean)
		mata: T[`row',`col']=st_numscalar("p")
	}
}
//set trace off
mata:st_matrix("T",T)
matrix rownames T=`rownames'
matrix colnames T=`colnames'
matrix list T, format(%3.2f)

error: pathspec 'tables-for-conditional-use.do' did not match any file(s) known to git


t/defaults-nested/clean fails on MacOS X.

It seems on OSX find behaves differently (probably from linux):

jtang@exia:~/develop/redo $ make clean
./redo clean
redo  clean
redo    t/clean
redo      t/example/clean
redo      t/curse/clean
redo      t/deps/clean
redo        t/deps/basic/clean
redo        t/deps/dirtest/clean
redo      t/space dir/clean
redo      t/stamp/clean
redo      t/defaults-flat/clean
redo      t/defaults-nested/clean
find: illegal option -- n
find: illegal option -- a
find: illegal option -- m
find: illegal option -- e
find: *~: No such file or directory
redo      t/defaults-nested/clean: exit code 1
redo    t/clean: exit code 1
redo  clean: exit code 1
make: *** [clean] Error 1

This fixes it for me.

exec >&2
find . -name '*~' -exec rm -f {} \;
rm -f a/b/file a/b/file.x.y.z a/b/file.y.z a/b/file.z \
	a/d/file a/d/file.x.y.z a/d/file.y.z a/d/file.z \
	a/file a/file.x.y.z a/file.y.z a/file.z \
	file.x.y.z file.z file

exec >&2
find -name '*~' -exec rm -f {} \;
rm -f a/b/file a/b/file.x.y.z a/b/file.y.z a/b/file.z \
	a/d/file a/d/file.x.y.z a/d/file.y.z a/d/file.z \
	a/file a/file.x.y.z a/file.y.z a/file.z \
	file.x.y.z file.z file


iematach : output

iematach : output

Committ with several output implementations. Display how many
obsrevations are excluded and why. (also added more specific reasons for
why an observations was omitted from the matching.) Hlines. And the
output resutl table. Added

	cap program drop 	iematch
	    program define	iematch

		noi di "Command OK!"

		syntax  [if] [in]  , 					///
			GRPdummy(varname) 					///
			MATCHvar(varname) 					///
			[									///
			IDvar(varname)						///
			m1									///
			maxdiff(numlist max = 1 min = 1) 	///
			seedok						 		///
			MATCHIDname(string)					///
			MATCHDIffname(string)				///
			MATCHREsultname(string)				///
			MATCHCOuntname(string)				///
			]

		*****
		*1 format errors as smcl
		*2 option to disable countdown
		*5 a table with results outputted

		noi di "Syntax OK!"

		pause on

		qui {

		********************************
		*
		*	Gen temp sort and merge var
		*
		********************************

		tempvar originalSort ifinvar

		gen `originalSort' = _n

		preserve

*Testing input
if 1 {

			local obsexcludstring ""

			*Deal with if and in and display info.
			if "`if'`in'" != "" {

				gen `ifinvar' = 1 `if'`in'

				count if `ifinvar' != 1
				if `r(N)' > 0 {

					*This is not an error just outputting the number
					local obsexcludstring "`obsexcludstring'`r(N)' observation(s) were excluded in {inp:if}/{inp:in}: (`if'`in').{break}"

				}

				keep `if'`in'
			}

			********************************
			*
			*	Checking group dummy
			*
			********************************

			*Test that the group dummy is 1, 0 or missing
			cap assert inlist(`grpdummy', 1, 0, .) | `grpdummy' > .
			if _rc != 0 {

				di as error "{pstd}The variable in grpdummy(`grpdummy') is not a dummy variable. The variable is only allowed to have the values 1, 0 or missing. Observations with missing varaibles in the grpdummy are ignored by this command.{p_end}"
				error _rc
			}

			**Exclude obs with missing value in groupdummy

			*Count number of obs to be dropped and and output that number if more than zero
			count if missing(`grpdummy')
			if `r(N)' > 0 {

				*This is not an error just outputting the number
				local obsexcludstring  "`obsexcludstring'`r(N)' observation(s) were excluded due to missing value in  grpdummy(`grpdummy').{break}"
			}
			*Drop obs with missing
			drop if missing(`grpdummy')

			********************************
			*
			*	Checking match continous var
			*
			********************************

			*Test that the continous is numeric
			cap confirm numeric variable `matchvar'
			if _rc != 0 {

				noi di as error "{pstd}The variable to match on specified in matchvar(`matchvar') is not a numeric variable.{p_end}"
				error 109

			}

			**All variables with value 1 or 0 in the group dummy and
			* not excluded by if/in must have a value in matchvar
			count if missing(`matchvar')
			if `r(N)' > 0 {
				local obsexcludstring  "`obsexcludstring'`r(N)' observation(s) were excluded due to missing value in matchvar(`matchvar').{break}"

			}
			*Drop obs with missing
			drop if missing(`matchvar')

			********************************
			*
			*	Checking match var and group dummy are unique
			*
			********************************

			if "`seedok'" == "" {

				**test that there are no duplicates in match
				* var within each type of observation
				cap isid `matchvar' `grpdummy'

				if _rc != 0 {

					noi di as error "{pstd}There are base observations or target observations {...}"
					noi di as error "with duplicate values in matchvar(`matchvar'). To guarantee {...}"
					noi di as error "a replicable match you must {help seed:set a seed}. To supress {...}"
					noi di as error "this error message after you have set a the seed, or if a {...}"
					noi di as error "replicable match is not important to you, use option {inp:seedok}{p_end}"
					error 198

				}
			}

			********************************
			*
			*	Checking that there are more target
			*	obs than base obs in a 1-to-1 match
			*
			********************************

			if "`m1'" == "" {

				*Count number of base vars
				count if `grpdummy' == 1
				local numBaseObs `r(N)'

				*Count number of target vars
				count if `grpdummy' == 0
				local numTrgtObs `r(N)'

				*Test that there are more target
				cap assert `numTrgtObs' >= `numBaseObs'

				if _rc != 0 {

					noi di as error "{pstd}There are more base observations than target observations. This is not allowed in a one-to-one match. See option {inp:m1} for an alternaitve matching where it is allowed to have more base observations than target ovbservations.{p_end}"
					error _rc
				}
			}

			********************************
			*
			*	Checking duplicates in variable names in options
			*
			********************************

			*Create a local of all varnames used in any option
			local allnewvars `idvar' `matchidname' `matchdiffname' `matchresult'

			*Check if there are any duplicates in the local of all varnames in options
			local dupnewvars : list dups allnewvars

			*Throw error if there were any duplicates
			if "`dupnewvars'" != "" {

				di as error "{pstd}The same new variable name was used twice or more in the options generating a new variable. Go back and check syntax.{p_end}"
				error 198

			}

			********************************
			*
			*	Checking ID var
			*
			********************************

			*Checking set-up for the ID var used for _matchID
			if "`idvar'" == "" {

				*Copy this name
				local idvar _ID

				*Make sure that the default name _ID is not already used
				cap confirm variable `idvar'
				if _rc == 0 {

					di as error "{pstd}A variable with name `idvar' is already defined. Either drop this variable or specify a variable using idvar() that fully and uniquely identifies the data set.{p_end}"
					error 110

				}

				*Generate the ID var from row number
				gen `idvar' = _n

				*Store local indicating ID var generated has type numeric
				local IDtypeNumeric 1

			}
			else {

				*Make sure that user specified ID is uniquely and fully identifying the observations
				cap isid `idvar'
				if _rc != 0 {

					di as error "{pstd}Variable `idvar' specified in idvar() does not fully and uniquely identify the observations in the data set. Meaning that `idvar' is not allowed to have any duplicates or missing values. Make `idvar' uniquly and fully idnetifying or exclude the varaibleas using {inp:if} or {inp:in}.{p_end}"
					error 450

				}

				*Test if ID var is string or numeric
				cap confirm numeric variable `idvar'
				if _rc == 0 {

					*Store local indicating ID var type is numeric
					local IDtypeNumeric 1
				}
				else {

					*Store local indicating ID var type is numeric
					local IDtypeNumeric 0
				}
			}

			********************************
			*
			*	Checking and generating the MatchID and the MatchDiff var
			*
			********************************

			*Test input from user or test if deafault value is valiable
			iematchMatchVarCheck _matchID `matchidname'
			local matchIDname "`r(validVarName)'"

			*Allow the ID var used to be string
			if `IDtypeNumeric' == 1 {
				gen  `matchIDname' = .
			}
			else {
				gen  `matchIDname' = ""
			}

			*If many-to-one match used
			if "`m1'" != "" {
				iematchMatchVarCheck _matchCount `matchcountname'
				local matchCountName "`r(validVarName)'"
				gen `matchCountName' = .
			}
			else {

				*Option match count name is not allowed if it is a one-to-one match
				if "`matchcountname'" != "" {

					di as error "{pstd}Option {inp:matchcountname()} is only allowed in combination with option {inp:m1}.{p_end}"
					error 198
				}
			}

			iematchMatchVarCheck _matchDiff `matchdiffname'
			local matchDiffName "`r(validVarName)'"
			gen `matchDiffName' = .

			iematchMatchVarCheck _matchResult `matchresultname'
			local matchReasonName "`r(validVarName)'"
			gen `matchReasonName' = .

			*Create a label for missing values that explains no match
			label define matchLabel 0 "Not Matched" 1 "Matched" .i "Obs excluded due to if/in" .g "Missing value in `grpdummy'" .m "Missing value in `matchvar'" .d "No match within maxdiff"

			*Apply the label
			label value `matchReasonName' matchLabel

}

			********************************
			*
			*	Output exclude string
			*
			********************************

			if "`obsexcludstring'" != "" {

				noi di ""
				noi di "{hline}"
				noi di ""
				noi di "{pstd}{ul:Observations are excluded from the matching for the following reasons:}{break}"
				noi di "`obsexcludstring'{p_end}"

			}

		********************************
		*	Start matching
		********************************

			********************************
			*
			*	Creating tempvar used
			*
			********************************

			*Initiate the temporary variables used by this command
			tempvar prefID prefDiff matched

			gen `prefDiff' 		= .
			gen byte `matched' 	= 0

			*Allow the ID var used to be string
			if `IDtypeNumeric' == 1 {
				gen  `prefID' = .
			}
			else {
				gen  `prefID' = ""
			}

			** Generate the inverse of the matchvar to sort descending (gsort is too slow),
			*  a random var to seperate two values with the same match var, and the inverse
			*  of the random var for when sorting descending.
			tempvar rand invsort invrand

			sort `matchvar'
			gen  `invsort' = -1 * `matchvar'

			gen    `rand' = uniform()
			gen `invrand' = -1 * `rand'

			***********
			*Tempvars for matching

			*Diffvars, they are always numeric
			tempvar					 diffup   diffdo   valUp_0   valDo_0   valUp_1   valDo_1
			local 	 updownTempVars `diffup' `diffdo' `valUp_0' `valDo_0' `valUp_1' `valDo_1'

			foreach tempVar of local updownTempVars {

				gen `tempVar' = .
			}

			*ID vars, allowed to be both numeric and string
			tempvar					  	IDup   IDdo   IDup_0   IDdo_0   IDup_1   IDdo_1
			local 	 updownIDTempVars  `IDup' `IDdo' `IDup_0' `IDdo_0' `IDup_1' `IDdo_1'

			foreach tempVar of local updownIDTempVars {

				*Allow the ID var used to be string
				if `IDtypeNumeric' == 1 {
					gen  `tempVar' = .
				}
				else {
					gen  `tempVar' = ""
				}
			}

			***************************
			*
			*	One to one match
			*
			***************************

			if "`m1'" == "" {

				noi di ""
				noi di "{hline}{break}"
				noi di "{pstd}{ul:Matching one-to-one. Base observations left to match:}{p_end}"
				count if `grpdummy' == 1 & `matched' == 0
				local left2Match = `r(N)'
				noi di "{pstd}`left2Match' " _c

				*di "`idvar'"
				*di "`IDtypeNumeric'"
				*pause on
				*pause

				while (`left2Match' > 0) {

					*noi di 0

					**For all observations still to be matched, assign the preferred
					* match among the other unmatched observations
					qui updatePrefDiffPreffID `prefID' `prefDiff' `matchvar' `invsort' `idvar' `grpdummy' `matched' `rand' `invrand' `updownTempVars' `updownIDTempVars'

					*noi di 1

					if "`maxdiff'" != "" {

						replace `matched' 			= 1		if `prefDiff' > `maxdiff' & `grpdummy' == 1
						replace `matchReasonName' 	= .d 	if `prefDiff' > `maxdiff' & `grpdummy' == 1

						*Allow the ID var used to be string
						if `IDtypeNumeric' == 1 {
							replace `prefID'		= .		if `prefDiff' > `maxdiff'
						}
						else {
							replace `prefID'		= ""	if `prefDiff' > `maxdiff'
						}
					}

					*noi di 2

					replace `matched' = 1 if `matched' == 0 & `prefID' == `idvar'[_n-1] & `prefID'[_n-1] == `idvar'
					replace `matched' = 1 if `matched' == 0 & `prefID' == `idvar'[_n+1] & `prefID'[_n+1] == `idvar'

					*noi di 3

					count if `grpdummy' == 1 & `matched' == 0
					local left2Match = `r(N)'
					noi di "`left2Match' " _c

				}
				noi di "{p_end}" _c

			}

			***************************
			*
			*	Many to one match
			*
			***************************
			else {

				updatePrefDiffPreffID `prefID' `prefDiff' `matchvar' `invsort' `idvar' `grpdummy' `matched' `rand' `invrand' `updownTempVars' `updownIDTempVars'

				if "`maxdiff'" != "" {

					replace `matched' 			= 1		if `prefDiff' > `maxdiff' & `grpdummy' == 1
					replace `matchReasonName' 	= .d 	if `prefDiff' > `maxdiff' & `grpdummy' == 1

					*Allow the ID var used to be string
					if `IDtypeNumeric' == 1 {
						replace `prefID'		= .		if `prefDiff' > `maxdiff'
					}
					else {
						replace `prefID'		= ""	if `prefDiff' > `maxdiff'
					}

				}

				replace `prefID'			=  `idvar' if `grpdummy' == 0
				bys 	`prefID' 			:   replace `matchCountName' = _N - 1

				**Replace prefID to missing for target obs that had no base
				* obs matched to it. T
				if `IDtypeNumeric' == 1 {
					*Id var is numeric
					replace `prefID'		= .		if `matchCountName' == 0
				}
				else {
					*id var is string
					replace `prefID'		= ""	if `matchCountName' == 0
				}

				*Only target obs with base obs prefering it are matched
				replace	 `matched' 			= 1		if `matchCountName' != 0

				*Remove values for target obs that were not matched
				replace  `matchCountName'	= . 	if `matchCountName' == 0
			}

			*Return vars
			replace `matchDiffName' 	= `prefDiff'	if `matched' == 1
			replace `matchIDname' 		= `idvar' 		if `matched' == 1 & `grpdummy' == 0
			replace `matchIDname' 		= `prefID' 		if `matched' == 1 & `grpdummy' == 1

			*Target obs not used
			replace `matchReasonName' = 0 if `matched' == 0 & `grpdummy' == 0

			*only keep output vars
			keep `matchIDname' `matchDiffName' `idvar' `originalSort' `matchReasonName' `matchCountName'

			tempfile mergefile

			save `mergefile'

		restore

		tempvar mergevar ifinvar

		merge 1:1  `originalSort' using `mergefile', gen(`mergevar')

		replace `matchReasonName' = .m if missing(`matchvar')
		replace `matchReasonName' = .g if missing(`grpdummy')

		if "`if'`in'" != "" {

			gen `ifinvar' = 1 `if'`in'
			replace `matchReasonName' = .i if `ifinvar' != 1
		}

		replace `matchReasonName' = 1 if `matchReasonName' == .

		*comress the variables generated
		compress  `matchIDname' `matchDiffName' `matchReasonName' `matchCountName'

		noi outputTable `matchReasonName' `grpdummy'

		sort `originalSort'

	}

	end

*Testing input (functions)
 if 1 {
	*Cheack matchVar input
	cap program drop 	iematchMatchVarCheck
		program define 	iematchMatchVarCheck  , rclass

		args defaultName userName

		if "`defaultName'" == "_matchID" 		local optionName matchidname
		if "`defaultName'" == "_matchDiff" 		local optionName matchdiffname
		if "`defaultName'" == "_matchResult" 	local optionName matchresult
		if "`defaultName'" == "_matchCount" 	local optionName matchcount

		*All the default names
		local dfltNms _noMatchReason _matchDiff _matchResult _matchCount

		*The other two default names
		local othDfltNms : list dfltNms - defaultName

		*Creating two locals with the deafult name in each local
		local Oth1 : word 1 of `othDfltNms'
		local Oth2 : word 2 of `othDfltNms'
		local Oth3 : word 3 of `othDfltNms'

		*Testing that the option name is not the same as the other variable's default name.
		if ("`userName'" == "`Oth1'" | "`userName'" == "`Oth2'" | "`userName'" == "`Oth3'" | "`userName'" == "_ID")  {

			noi di as error "{phang}The new name specified in `optionName'(`userName') is not allowed to be _ID, `Oth1', `Oth2', or `Oth3'{p_end}"
			error 198
		}

		*Checking set-up for the ID var used for _matchID
		if "`userName'" == "" {

			*CSet the default name
			local validMatchVarname `defaultName'

			*Make sure that the default name _ID is not already used
			cap confirm variable `validMatchVarname'
			if _rc == 0 {

				noi di as error "A variable with name `validMatchVarname' is already defined. Either drop this variable or specify a new variable name using `optionName'()."
				error 110

			}

		}

		else {

			*CSet the default name
			local validMatchVarname `userName'

			*Make sure that the default name _ID is not already used
			cap confirm variable `validMatchVarname'
			if _rc == 0 {

				noi di as error "The variable name specified in `optionName'(`userName') is already defined in the data set. Either drop this variable or specify a another variable name using `optionName'()."
				error 110

			}

		}

		*Testing that the new name is valid by creating a variable that is dropped immedeatly afterwards
		cap gen `validMatchVarname' = .

		if _rc != 0 {

			noi di as error "The variable name specified in `optionName'(`userName') is not a valid variable name."
			error _rc

		}
		drop `validMatchVarname'

		return local validVarName 	"`validMatchVarname'"

	end
}

*Matching functions
if 1 {

	** This function is called to assign the preferred match for all unmatched
	*  observations to any other unmatched observation. Returns a variable pref that is the
	cap program drop 	updatePrefDiffPreffID
		program define 	updatePrefDiffPreffID

		args prefID prefDiff matchvar invsort idvar grpvar matched rand invrand diffup diffdo valUp_0 valDo_0 valUp_1 valDo_1 IDup IDdo IDup_0 IDdo_0 IDup_1 IDdo_1

		*****************
		*Update possible matches with higher rank value
		sort `matched' `matchvar' `rand'

		updateBestValID 0 `matchvar' `idvar' `grpvar' `matched' `valUp_0' `IDup_0'
		updateBestValID 1 `matchvar' `idvar' `grpvar' `matched' `valUp_1' `IDup_1'

		*****************
		*Update possible matches with lower rank value
		sort `matched' `invsort' `invrand'

		updateBestValID 0 `matchvar' `idvar' `grpvar' `matched' `valDo_0' `IDdo_0'
		updateBestValID 1 `matchvar' `idvar' `grpvar' `matched' `valDo_1' `IDdo_1'

		*****************
		*Create one varaible common for both groups with diff upwards
		replace `diffup' 	= abs(`matchvar' - `valUp_1') if `grpvar' == 1
		replace `diffup' 	= abs(`matchvar' - `valUp_0') if `grpvar' == 0

		*Create one varaible common for both groups with diff downwards
		replace `diffdo' 	= abs(`matchvar' - `valDo_1') if `grpvar' == 1
		replace `diffdo' 	= abs(`matchvar' - `valDo_0') if `grpvar' == 0

		*Create one varaible common for both groups with ID upwards
		replace `IDup' 		= `IDup_1' 	if `grpvar' == 1
		replace `IDup' 		= `IDup_0' 	if `grpvar' == 0

		*Create one varaible common for both groups with ID downwards
		replace `IDdo' 		= `IDdo_1' 	if `grpvar' == 1
		replace `IDdo' 		= `IDdo_0' 	if `grpvar' == 0

		replace `prefID' 	= `IDdo' 	if `matched' == 0 & `diffdo' <= `diffup'
		replace `prefID' 	= `IDup' 	if `matched' == 0 & `diffdo' >  `diffup'

		replace `prefDiff' 	= `diffdo' 	if `matched' == 0 & `diffdo' <= `diffup'
		replace `prefDiff' 	= `diffup' 	if `matched' == 0 & `diffdo' >  `diffup'

	end

	** This function goes through the observatioins from top to down and copying
	*  the match value of the closest observation of the other group above to
	*  (bestVal) and the ccoprresponding ID to (bestID) for obe group at the time.
	*  To go from bottuom to top sort with invsort and apply this command.
	cap program drop 	updateBestValID
		program define 	updateBestValID

		args grpvl matchval idvar grpvar matched bestVal bestID

		*Test if ID var is string or numeric
		local IDNumeric 0
		cap confirm numeric variable `idvar'
		if _rc == 0 local IDNumeric 1

		*Reset all values
		replace `bestVal' 	= .
		if `IDNumeric' == 1 replace `bestID' 	= .
		if `IDNumeric' == 0 replace `bestID' 	= ""

		*Set the match value and ID of observations that are in the other group
		replace `bestVal'   = `matchval' 		if `grpvar' != `grpvl' & `matched' == 0
		replace `bestID'  	= `idvar' 			if `grpvar' != `grpvl' & `matched' == 0

		*Fill in that value from the observation in the other group until getting to another observation of the other group
							replace `bestVal'   = `bestVal'[_n-1]	if `bestVal' == .  & `matched' == 0
		if `IDNumeric' == 1 replace `bestID'  	= `bestID'[_n-1] 	if `bestID'	 == .  & `matched' == 0
		if `IDNumeric' == 0 replace `bestID'  	= `bestID'[_n-1] 	if `bestID'	 == "" & `matched' == 0

	end

}

	** This function goes through the observatioins from top to down and copying
	*  the match value of the closest observation of the other group above to
	*  (bestVal) and the ccoprresponding ID to (bestID) for obe group at the time.
	*  To go from bottuom to top sort with invsort and apply this command.
	cap program drop 	outputTable
		program define 	outputTable

		qui {
			args resultVar grpdum

			local maxResultLen 16

			local allResults 1 0 .d .i .g .m

			levelsof `resultVar' , missing local(resultsUsed)

			foreach result of local resultsUsed {

				if `result' == 1  local thisLen 7
				if `result' == 0  local thisLen 11
				if `result' == .d local thisLen 25
				if `result' == .i local thisLen 18
				if `result' == .g local thisLen 18
				if `result' == .m local thisLen 18

				local maxResultLen = max(`maxResultLen' , `thisLen')
			}

			local missingGrpDum 0
			count if missing(`grpdum')
			if `r(N)' > 0 local missingGrpDum 1

			local R1 "{col 4}{c |}"

			local col1width = `maxResultLen' + 3 //28
			local hli1 "{hline `col1width'}"
			local cen1 "{center `col1width':"

			local col2border = `maxResultLen' + 8 //33
			local R2  "{col `col2border'}{c |}"
			local R2a "{col `col2border'}"

			local col3border = `maxResultLen' + 19 //44
			local R3 "{col `col3border'}{c |}"

			local col4border = `maxResultLen' + 32 //57
			local R4 "{col `col4border'}{c |}"

			local grpdumCentre 23

			local lastT  	"{c RT}"
			local lastTdown	"{c RT}"
			local lastC  	"{c BRC}"

			if `missingGrpDum' {

				local lastT 		"{c +}{hline 9}{c RT}"
				local lastTdown 	"{c BT}{hline 9}{c RT}"
				local lastC 		"{c BT}{hline 9}{c BRC}"
				local missTitle 	"  missing "
				local grpdumCentre 	33

			}

			noi di ""
			noi di ""
			noi di "{hline}"
			noi di ""
			noi di "{pstd}{ul:Output of Matching Result:}{p_end}"
			noi di ""
			noi di "{col 5}`cen1'`resultVar'}`R2a' {centre `grpdumCentre':tmt }"
			noi di "{col 4}{c LT}`hli1'{c +}{hline `grpdumCentre'}{c RT}"
			noi di "`R1'`cen1'value and result}`R2' 1 (base)   0 (target) `missTitle'{c |}"
			noi di "{col 4}{c LT}`hli1'{c +}{hline 10}{c +}{hline 12}`lastT'"

			foreach result of local allResults {

				if `:list result in resultsUsed' {

					qui count if `resultVar' == `result' & `grpdum' == 1
					local numBase : display %9.0gc `r(N)'

					qui count if `resultVar' == `result' & `grpdum' == 0
					local numTarg : display %9.0gc `r(N)'

					if `missingGrpDum' {

						qui count if `resultVar' == `result' & missing(`grpdum')
						local numMiss `r(N)'

						local missCol "{ralign 9 :`numMiss' }{c |}"

					}

					local numCols "`R2'{ralign 10 :`numBase' }`R3'{ralign 12 :`numTarg' }`R4'`missCol'"

					if `result' == 1  noi di "`R1' 1 Matched`numCols'"
					if `result' == 0  noi di "`R1' 0 Not matched`numCols'"
					if `result' == .d noi di "`R1'.d No match within maxdiff()`numCols'"
					if `result' == .i noi di "`R1'.i Excl. using if/in`numCols'"
					if `result' == .g noi di "`R1'.g Missing grpdummy()`numCols'"
					if `result' == .m noi di "`R1'.m Missing matchvar()`numCols'"
				}
			}
			noi di "{col 4}{c LT}`hli1'{c +}{hline 10}{c +}{hline 12}`lastT'"

			qui count if `grpdum' == 1
			local numBase : display %9.0gc `r(N)'

			qui count if `grpdum' == 0
			local numTarg : display %9.0gc `r(N)'

			if `missingGrpDum' {

				qui count if missing(`grpdum')
				local numMiss : display %9.0gc `r(N)'

				local missCol "{ralign 9 :`numMiss' }{c |}"

			}

			noi di "`R1'`cen1'N per group}`R2'{ralign 10 :`numBase' }`R3'{ralign 12 :`numTarg' }`R4'`missCol'"
			noi di "{col 4}{c LT}`hli1'{c +}{hline 10}{c BT}{hline 12}`lastTdown'"

			qui count
			local numTot : display %9.0gc `r(N)'

			noi di "`R1'`cen1'Total N}`R2'{centre `grpdumCentre':`numTot'}`R4'"
			noi di "{col 4}{c BLC}`hli1'{c BT}{hline `grpdumCentre'}{c BRC}"
		}
	end

	cap program drop 	iematch
	    program define	iematch

		noi di "Command OK!"

		syntax  [if] [in]  , 					///
			GRPdummy(varname) 					///
			MATCHvar(varname) 					///
			[									///
			IDvar(varname)						///
			m1									///
			maxdiff(numlist max = 1 min = 1) 	///
			seedok						 		///
			MATCHIDname(string)					///
			MATCHDIffname(string)				///
			MATCHREsultname(string)				///
			MATCHCOuntname(string)				///
			]

		*****
		*1 format errors as smcl
		*2 option to disable countdown
		*3 test not matchcount without m1
		*5 a table with results outputted

		noi di "Syntax OK!"

		pause on

		qui {

		********************************
		*
		*	Gen temp sort and merge var
		*
		********************************

		tempvar originalSort

		gen `originalSort' = _n

		preserve

*Testing input
if 1 {

			if "`if'`in'" != "" keep `if'`in'

			********************************
			*
			*	Checking group dummy
			*
			********************************

			*Test that the group dummy is 1, 0 or missing
			cap assert inlist(`grpdummy', 1, 0, .) | `grpdummy' > .
			if _rc != 0 {

				di as error "{pstd}The variable in grpdummy(`grpdummy') is not a dummy variable. The variable is only allowed to have the values 1, 0 or missing. Observations with missing varaibles in the grpdummy are ignored by this command.{p_end}"
				error _rc
			}

			**Exclude obs with missing value in groupdummy

			*Count number of obs to be dropped and and output that number if more than zero
			count if missing(`grpdummy')
			if `r(N)' > 0 {
				*This is not an error just outputting the number
				noi di "{pstd}`r(N)' observation(s) were excluded due to missing value in group dummy{p_end}"
			}
			*Drop obs with missing
			drop if missing(`grpdummy')

			********************************
			*
			*	Checking match continous var
			*
			********************************

			*Test that the continous is numeric
			cap confirm numeric variable `matchvar'
			if _rc != 0 {

				noi di as error "{pstd}The variable to match on specified in matchvar(`matchvar') is not a numeric variable.{p_end}"
				error 109

			}

			**All variables with value 1 or 0 in the group dummy and
			* not excluded by if/in must have a value in matchvar
			count if missing(`matchvar')
			if `r(N)' > 0 {
				noi di as error  "{pstd}`r(N)' observation(s) with either value 1 or 0 in grpdummy(`grpdummy') do not have a non-missing value in matchvar(`matchvar'). Either update the match variable or exclude those observations using {inp:if} or {inp:in}.{p_end}"
				error 416
			}

			********************************
			*
			*	Checking match var and group dummy are unique
			*
			********************************

			if "`seedok'" == "" {

				**test that there are no duplicates in match
				* var within each type of observation
				cap isid `matchvar' `grpdummy'

				if _rc != 0 {

					noi di as error "{pstd}There are base observations or target observations with duplicate values in matchvar(`matchvar'). To guarantee a replicable match you must {help seed:set a seed}. To supress this error message after you have set a the seed, or if a replicable match is not important to you, use option {inp:seedok}{p_end}"
					error _rc

				}
			}

			********************************
			*
			*	Checking that there are more target
			*	obs than base obs in a 1-to-1 match
			*
			********************************

			if "`m1'" == "" {

				*Count number of base vars
				count if `grpdummy' == 1
				local numBaseObs `r(N)'

				*Count number of target vars
				count if `grpdummy' == 0
				local numTrgtObs `r(N)'

				*Test that there are more target
				cap assert `numTrgtObs' >= `numBaseObs'

				if _rc != 0 {

					noi di as error "{pstd}There are more base observations than target observations. This is not allowed in a one-to-one match. See option {inp:m1} for an alternaitve matching where it is allowed to have more base observations than target ovbservations.{p_end}"
					error _rc
				}
			}

			********************************
			*
			*	Checking duplicates in variable names in options
			*
			********************************

			*Create a local of all varnames used in any option
			local allnewvars `idvar' `matchidname' `matchdiffname' `matchresult'

			*Check if there are any duplicates in the local of all varnames in options
			local dupnewvars : list dups allnewvars

			*Throw error if there were any duplicates
			if "`dupnewvars'" != "" {

				di as error "{pstd}The same new variable name was used twice or more in the options generating a new variable. Go back and check syntax.{p_end}"
				error 198

			}

			********************************
			*
			*	Checking ID var
			*
			********************************

			*Checking set-up for the ID var used for _matchID
			if "`idvar'" == "" {

				*Copy this name
				local idvar _ID

				*Make sure that the default name _ID is not already used
				cap confirm variable `idvar'
				if _rc == 0 {

					di as error "{pstd}A variable with name `idvar' is already defined. Either drop this variable or specify a variable using idvar() that fully and uniquely identifies the data set.{p_end}"
					error 110

				}

				*Generate the ID var from row number
				gen `idvar' = _n

				*Store local indicating ID var generated has type numeric
				local IDtypeNumeric 1

			}
			else {

				*Make sure that user specified ID is uniquely and fully identifying the observations
				cap isid `idvar'
				if _rc != 0 {

					di as error "{pstd}Variable `idvar' specified in idvar() does not fully and uniquely identify the observations in the data set. Meaning that `idvar' is not allowed to have any duplicates or missing values. Make `idvar' uniquly and fully idnetifying or exclude the varaibleas using {inp:if} or {inp:in}.{p_end}"
					error 450

				}

				*Test if ID var is string or numeric
				cap confirm numeric variable `idvar'
				if _rc == 0 {

					*Store local indicating ID var type is numeric
					local IDtypeNumeric 1
				}
				else {

					*Store local indicating ID var type is numeric
					local IDtypeNumeric 0
				}
			}

			********************************
			*
			*	Checking and generating the MatchID and the MatchDiff var
			*
			********************************

			*Test input from user or test if deafault value is valiable
			iematchMatchVarCheck _matchID `matchidname'
			local matchIDname "`r(validVarName)'"

			*Allow the ID var used to be string
			if `IDtypeNumeric' == 1 {
				gen  `matchIDname' = .
			}
			else {
				gen  `matchIDname' = ""
			}

			*If many-to-one match used
			if "`m1'" != "" {
				iematchMatchVarCheck _matchCount `matchcountname'
				local matchCountName "`r(validVarName)'"
				gen `matchCountName' = .
			}
			else {

				*Option match count name is not allowed if it is a one-to-one match
				if "`matchcountname'" != "" {

					di as error "{pstd}Option {inp:matchcountname()} is only allowed in combination with option {inp:m1}.{p_end}"
					error 198
				}
			}

			iematchMatchVarCheck _matchDiff `matchdiffname'
			local matchDiffName "`r(validVarName)'"
			gen `matchDiffName' = .

			iematchMatchVarCheck _matchOrReason `matchresultname'
			local matchReasonName "`r(validVarName)'"
			gen `matchReasonName' = .

			*Create a label for missing values that explains no match
			label define matchLabel 0 "Not Matched" 1 "Matched" .n "Obs not included in match" .m "No match within maxdiff"

			*Apply the label
			label value `matchReasonName' matchLabel

}

		********************************
		*	Start matching
		********************************

			********************************
			*
			*	Creating tempvar used
			*
			********************************

			*Initiate the temporary variables used by this command
			tempvar prefID prefDiff matched

			gen `prefDiff' 		= .
			gen byte `matched' 	= 0

			*Allow the ID var used to be string
			if `IDtypeNumeric' == 1 {
				gen  `prefID' = .
			}
			else {
				gen  `prefID' = ""
			}

			** Generate the inverse of the matchvar to sort descending (gsort is too slow),
			*  a random var to seperate two values with the same match var, and the inverse
			*  of the random var for when sorting descending.
			tempvar rand invsort invrand

			sort `matchvar'
			gen  `invsort' = -1 * `matchvar'

			gen    `rand' = uniform()
			gen `invrand' = -1 * `rand'

			***********
			*Tempvars for matching

			*Diffvars, they are always numeric
			tempvar					 diffup   diffdo   valUp_0   valDo_0   valUp_1   valDo_1
			local 	 updownTempVars `diffup' `diffdo' `valUp_0' `valDo_0' `valUp_1' `valDo_1'

			foreach tempVar of local updownTempVars {

				gen `tempVar' = .
			}

			*ID vars, allowed to be both numeric and string
			tempvar					  	IDup   IDdo   IDup_0   IDdo_0   IDup_1   IDdo_1
			local 	 updownIDTempVars  `IDup' `IDdo' `IDup_0' `IDdo_0' `IDup_1' `IDdo_1'

			foreach tempVar of local updownIDTempVars {

				*Allow the ID var used to be string
				if `IDtypeNumeric' == 1 {
					gen  `tempVar' = .
				}
				else {
					gen  `tempVar' = ""
				}
			}

			***************************
			*
			*	One to one match
			*
			***************************

			if "`m1'" == "" {

				noi di ""
				noi di "{pstd}Base observations left to match: {p_end}"
				count if `grpdummy' == 1 & `matched' == 0
				local left2Match = `r(N)'
				noi di "{pstd}`left2Match' " _c

				*di "`idvar'"
				*di "`IDtypeNumeric'"
				*pause on
				*pause

				while (`left2Match' > 0) {

					*noi di 0

					**For all observations still to be matched, assign the preferred
					* match among the other unmatched observations
					qui updatePrefDiffPreffID `prefID' `prefDiff' `matchvar' `invsort' `idvar' `grpdummy' `matched' `rand' `invrand' `updownTempVars' `updownIDTempVars'

					*noi di 1

					if "`maxdiff'" != "" {

						replace `matched' 			= 1		if `prefDiff' > `maxdiff' & `grpdummy' == 1
						replace `matchReasonName' 	= .m 	if `prefDiff' > `maxdiff' & `grpdummy' == 1

						*Allow the ID var used to be string
						if `IDtypeNumeric' == 1 {
							replace `prefID'		= .		if `prefDiff' > `maxdiff'
						}
						else {
							replace `prefID'		= ""	if `prefDiff' > `maxdiff'
						}
					}

					*noi di 2

					replace `matched' = 1 if `matched' == 0 & `prefID' == `idvar'[_n-1] & `prefID'[_n-1] == `idvar'
					replace `matched' = 1 if `matched' == 0 & `prefID' == `idvar'[_n+1] & `prefID'[_n+1] == `idvar'

					*noi di 3

					count if `grpdummy' == 1 & `matched' == 0
					local left2Match = `r(N)'
					noi di "`left2Match' " _c

				}
				noi di "{p_end}" _c

			}

			***************************
			*
			*	Many to one match
			*
			***************************
			else {

				updatePrefDiffPreffID `prefID' `prefDiff' `matchvar' `invsort' `idvar' `grpdummy' `matched' `rand' `invrand' `updownTempVars' `updownIDTempVars'

				if "`maxdiff'" != "" {

					replace `matched' 			= 1		if `prefDiff' > `maxdiff' & `grpdummy' == 1
					replace `matchReasonName' 	= .m 	if `prefDiff' > `maxdiff' & `grpdummy' == 1

					*Allow the ID var used to be string
					if `IDtypeNumeric' == 1 {
						replace `prefID'		= .		if `prefDiff' > `maxdiff'
					}
					else {
						replace `prefID'		= ""	if `prefDiff' > `maxdiff'
					}

				}

				replace `prefID'			=  `idvar' if `grpdummy' == 0
				bys 	`prefID' 			:   replace `matchCountName' = _N - 1

				**Replace prefID to missing for target obs that had no base
				* obs matched to it. T
				if `IDtypeNumeric' == 1 {
					*Id var is numeric
					replace `prefID'		= .		if `matchCountName' == 0
				}
				else {
					*id var is string
					replace `prefID'		= ""	if `matchCountName' == 0
				}

				*Only target obs with base obs prefering it are matched
				replace	 `matched' 			= 1		if `matchCountName' != 0

				*Remove values for target obs that were not matched
				replace  `matchCountName'	= . 	if `matchCountName' == 0
			}

			*Return vars
			replace `matchDiffName' 	= `prefDiff'	if `matched' == 1
			replace `matchIDname' 		= `idvar' 		if `matched' == 1 & `grpdummy' == 0
			replace `matchIDname' 		= `prefID' 		if `matched' == 1 & `grpdummy' == 1

			*Target obs not used
			replace `matchReasonName' = 0 if `matched' == 0 & `grpdummy' == 0

			*only keep output vars
			keep `matchIDname' `matchDiffName' `idvar' `originalSort' `matchReasonName' `matchCountName'

			tempfile mergefile

			save `mergefile'

		restore

		tempvar mergevar

		merge 1:1  `originalSort' using `mergefile', gen(`mergevar')

		replace `matchReasonName' = .n if `mergevar' == 1
		replace `matchReasonName' = 1 if `matchReasonName' == .

		*comress the variables generated
		compress  `matchIDname' `matchDiffName' `matchReasonName' `matchCountName'

		*Output result to user
		noi tab `matchReasonName' `grpdummy', m

		sort `originalSort'

	}

	end

*Testing input (functions)
 if 1 {
	*Cheack matchVar input
	cap program drop 	iematchMatchVarCheck
		program define 	iematchMatchVarCheck  , rclass

		args defaultName userName

		if "`defaultName'" == "_matchID" 		local optionName matchidname
		if "`defaultName'" == "_matchDiff" 		local optionName matchdiffname
		if "`defaultName'" == "_matchOrReason" 	local optionName matchresult
		if "`defaultName'" == "_matchCount" 	local optionName matchcount

		*All the default names
		local dfltNms _noMatchReason _matchDiff _matchOrReason _matchCount

		*The other two default names
		local othDfltNms : list dfltNms - defaultName

		*Creating two locals with the deafult name in each local
		local Oth1 : word 1 of `othDfltNms'
		local Oth2 : word 2 of `othDfltNms'
		local Oth3 : word 3 of `othDfltNms'

		*Testing that the option name is not the same as the other variable's default name.
		if ("`userName'" == "`Oth1'" | "`userName'" == "`Oth2'" | "`userName'" == "`Oth3'" | "`userName'" == "_ID")  {

			noi di as error "{phang}The new name specified in `optionName'(`userName') is not allowed to be _ID, `Oth1', `Oth2', or `Oth3'{p_end}"
			error 198
		}

		*Checking set-up for the ID var used for _matchID
		if "`userName'" == "" {

			*CSet the default name
			local validMatchVarname `defaultName'

			*Make sure that the default name _ID is not already used
			cap confirm variable `validMatchVarname'
			if _rc == 0 {

				noi di as error "A variable with name `validMatchVarname' is already defined. Either drop this variable or specify a new variable name using `optionName'()."
				error 110

			}

		}

		else {

			*CSet the default name
			local validMatchVarname `userName'

			*Make sure that the default name _ID is not already used
			cap confirm variable `validMatchVarname'
			if _rc == 0 {

				noi di as error "The variable name specified in `optionName'(`userName') is already defined in the data set. Either drop this variable or specify a another variable name using `optionName'()."
				error 110

			}

		}

		*Testing that the new name is valid by creating a variable that is dropped immedeatly afterwards
		cap gen `validMatchVarname' = .

		if _rc != 0 {

			noi di as error "The variable name specified in `optionName'(`userName') is not a valid variable name."
			error _rc

		}
		drop `validMatchVarname'

		return local validVarName 	"`validMatchVarname'"

	end
}

*Matching functions
if 1 {

	** This function is called to assign the preferred match for all unmatched
	*  observations to any other unmatched observation. Returns a variable pref that is the
	cap program drop 	updatePrefDiffPreffID
		program define 	updatePrefDiffPreffID

		args prefID prefDiff matchvar invsort idvar grpvar matched rand invrand diffup diffdo valUp_0 valDo_0 valUp_1 valDo_1 IDup IDdo IDup_0 IDdo_0 IDup_1 IDdo_1

		*****************
		*Update possible matches with higher rank value
		sort `matched' `matchvar' `rand'

		updateBestValID 0 `matchvar' `idvar' `grpvar' `matched' `valUp_0' `IDup_0'
		updateBestValID 1 `matchvar' `idvar' `grpvar' `matched' `valUp_1' `IDup_1'

		*****************
		*Update possible matches with lower rank value
		sort `matched' `invsort' `invrand'

		updateBestValID 0 `matchvar' `idvar' `grpvar' `matched' `valDo_0' `IDdo_0'
		updateBestValID 1 `matchvar' `idvar' `grpvar' `matched' `valDo_1' `IDdo_1'

		*****************
		*Create one varaible common for both groups with diff upwards
		replace `diffup' 	= abs(`matchvar' - `valUp_1') if `grpvar' == 1
		replace `diffup' 	= abs(`matchvar' - `valUp_0') if `grpvar' == 0

		*Create one varaible common for both groups with diff downwards
		replace `diffdo' 	= abs(`matchvar' - `valDo_1') if `grpvar' == 1
		replace `diffdo' 	= abs(`matchvar' - `valDo_0') if `grpvar' == 0

		*Create one varaible common for both groups with ID upwards
		replace `IDup' 		= `IDup_1' 	if `grpvar' == 1
		replace `IDup' 		= `IDup_0' 	if `grpvar' == 0

		*Create one varaible common for both groups with ID downwards
		replace `IDdo' 		= `IDdo_1' 	if `grpvar' == 1
		replace `IDdo' 		= `IDdo_0' 	if `grpvar' == 0

		replace `prefID' 	= `IDdo' 	if `matched' == 0 & `diffdo' <= `diffup'
		replace `prefID' 	= `IDup' 	if `matched' == 0 & `diffdo' >  `diffup'

		replace `prefDiff' 	= `diffdo' 	if `matched' == 0 & `diffdo' <= `diffup'
		replace `prefDiff' 	= `diffup' 	if `matched' == 0 & `diffdo' >  `diffup'

	end

	** This function goes through the observatioins from top to down and copying
	*  the match value of the closest observation of the other group above to
	*  (bestVal) and the ccoprresponding ID to (bestID) for obe group at the time.
	*  To go from bottuom to top sort with invsort and apply this command.
	cap program drop 	updateBestValID
		program define 	updateBestValID

		args grpvl matchval idvar grpvar matched bestVal bestID

		*Test if ID var is string or numeric
		local IDNumeric 0
		cap confirm numeric variable `idvar'
		if _rc == 0 local IDNumeric 1

		*Reset all values
		replace `bestVal' 	= .
		if `IDNumeric' == 1 replace `bestID' 	= .
		if `IDNumeric' == 0 replace `bestID' 	= ""

		*Set the match value and ID of observations that are in the other group
		replace `bestVal'   = `matchval' 		if `grpvar' != `grpvl' & `matched' == 0
		replace `bestID'  	= `idvar' 			if `grpvar' != `grpvl' & `matched' == 0

		*Fill in that value from the observation in the other group until getting to another observation of the other group
							replace `bestVal'   = `bestVal'[_n-1]	if `bestVal' == .  & `matched' == 0
		if `IDNumeric' == 1 replace `bestID'  	= `bestID'[_n-1] 	if `bestID'	 == .  & `matched' == 0
		if `IDNumeric' == 0 replace `bestID'  	= `bestID'[_n-1] 	if `bestID'	 == "" & `matched' == 0

	end

}


experimenting with solution

experimenting with solution

*! version 5.3 14NOV2017  Kristoffer Bjarkefur kbjarkefur@worldbank.org

	cap program drop 	iematch2
	    program define	iematch2

		syntax  [if] [in]  , 					///
			GRPdummy(varname) 					///
			MATCHvar(varname) 					///
			[									///
			IDvar(varname)						///
			m1									///
			maxdiff(numlist max = 1 min = 1) 	///
			maxmatch(numlist >0 integer) 		///
			seedok						 		///
			MATCHIDname(string)					///
			MATCHDIffname(string)				///
			MATCHREsultname(string)				///
			MATCHCOuntname(string)				///
			replace								///
			]

		*****

	qui {

		* Set version
		version 11.0

		********************************
		*
		*	Gen temp sort and merge var
		*
		********************************

		tempvar originalSort ifinvar

		**Generate a variable that is used
		* to restore original sort.
		gen `originalSort' = _n

		preserve

			* String used to store why and how
			*  many observations are excluded.
			local obsexcludstring ""

			*Dummy local that is 1 if replace is used
			if "`replace'" == "" local REPLACE_USED 0
			if "`replace'" != "" local REPLACE_USED 1

			*Deal with if and in and display info.
			if "`if'`in'" != "" {

				* Gen dummy that is 1 when if/in is true. Then
				* count when this dummy is not 1. Ther is no way
				* to negate `if'`in'
				gen 	 `ifinvar'  = 1 `if'`in'
				count if `ifinvar' != 1
				if `r(N)' > 0 {

					*This is not an error just outputting the number
					local obsexcludstring "`obsexcludstring'`r(N)' observation(s) were excluded in {inp:if}/{inp:in}: (`if'`in').{break}"

				}

				*Drop variables excluded by `if'`in'
				keep `if'`in'
			}

		********************************
		*
		*	Checking ID var (and create if needed)
		*
		********************************

			*Checking set-up for the ID var used for _matchID
			if "`idvar'" == "" {

				*Copy this name
				local idvar _ID

				*Make sure that the default name _ID is not already used
				cap confirm variable `idvar'
				if _rc == 0 {

					*Test if option replace is used
					if `REPLACE_USED' == 1 {
						*Replace option is used, drop the variable with the name specified
						drop `idvar'
					}
					else {
						*Replace is not used, throw an error.
						di as error "{pstd}A variable with name `idvar' is already defined. Either drop this variable manually, use the replace option or specify a variable using idvar() that fully and uniquely identifies the data set.{p_end}"
						error 110
					}
				}

				*Generate the ID var from row number
				gen `idvar' = _n
			}

			*Make sure that idvar is uniquelly and fully identifying
			cap isid `idvar'
			if _rc != 0 {

				di as error "{pstd}Variable `idvar' specified in idvar() does not fully and uniquely identify the observations in the data set. `idvar' either has duplicates or missing values which is not allowed. Make `idvar' uniquly and fully idnetifying or exclude the varaibleas using {inp:if} or {inp:in}.{p_end}"
				error 450
			}

			*local indicating assume ID is string
			local IDtypeNumeric 0

			*Change local to 1 if ID actally string
			cap confirm numeric variable `idvar'
			if _rc == 0 local IDtypeNumeric 1

		********************************
		*
		*	Checking duplicates in variable names in options
		*
		********************************

			*Create a local of all varnames used in any option
			local allnewvars `idvar' `matchidname' `matchdiffname' `matchresultname' `matchcountname'

			*Check if there are any duplicates in the local of all varnames in options
			local dupnewvars : list dups allnewvars

			*Throw error if there were any duplicates
			if "`dupnewvars'" != "" {

				noi di as error "{pstd}The same new variable name was used twice or more in the options generating a new variable. Go back and check syntax.{p_end}"
				error 198
			}

		********************************
		*
		*	Test the names used for output vars
		*
		********************************

			iematchMatchVarCheck 	_matchResult 	`REPLACE_USED' "`matchresultname'"
			local matchResultName 	"`r(validVarName)'"

			iematchMatchVarCheck 	_matchID 		`REPLACE_USED' "`matchidname'"
			local matchIDname 		"`r(validVarName)'"

			iematchMatchVarCheck 	_matchDiff 		`REPLACE_USED' "`matchdiffname'"
			local matchDiffName 	"`r(validVarName)'"

			if "`m1'" != "" {
			   iematchMatchVarCheck _matchCount 	`REPLACE_USED' "`matchcountname'"
			   local matchCountName "`r(validVarName)'"
			}

			*Option matchcountname() is not allowed if it is not a many-one match
			if "`matchcountname'" != "" & "`m1'" == "" {
				di as error "{pstd}Option {inp:matchcountname()} is only allowed in combination with option {inp:m1}.{p_end}"
				error 198
			}

		********************************
		*
		*	Create and label output vars
		*
		********************************

			* MATCH RESULT VAR
			label define 	 matchLabel 0 "Not Matched" 1 "Matched" .i "Obs excluded due to if/in" 			///
										.g "Missing value in `grpdummy'" .m "Missing value in `matchvar'" 	///
										.d "No match within maxdiff" .t "No more eligible target obs", replace

			gen 			`matchResultName' = .
			label variable	`matchResultName' "Matched obs = 1, not mathched = 0, all other different missing values"
			label value 	`matchResultName' matchLabel

			* MATCH ID VAR
			if `IDtypeNumeric' == 1 gen  `matchIDname' = .	//Main ID var is numeric
			if `IDtypeNumeric' == 0 gen  `matchIDname' = "" //Main ID var is string

			if "`m1'" != "" label variable	`matchIDname' "The ID of the target var in each matched group"	//If many to one
			if "`m1'" == "" label variable	`matchIDname' "The ID of the target var in each matched pair"	//If one to one

			* MATCH DIFF VAR
			gen 	`matchDiffName' = .
			if "`m1'" != "" label variable	`matchDiffName' "The difference in matchvar() between base obs and the target obs it matched with" 	//If many to one
			if "`m1'" == "" label variable	`matchDiffName' "The difference in matchvar() between base and target obs in each pair" 			//If one to one

			*Match count, only many-one
			if "`m1'" != "" {
				gen 			`matchCountName' = .
				label variable	`matchCountName' "The number of base obs this target obs matched with"
			}

		********************************
		*
		*	Keep only relevant vars
		*
		********************************

			*Keep only input vars and output vars
			keep  `grpdummy' `idvar' `matchvar'	`originalSort' `matchResultName' `matchIDname' `matchDiffName' `matchCountName'

		********************************
		*
		*	Checking group dummy
		*
		********************************

			*Test that the group dummy is 1, 0 or missing
			cap assert inlist(`grpdummy', 1, 0, .) | `grpdummy' > .
			if _rc != 0 {

				di as error "{pstd}The variable in grpdummy(`grpdummy') is not a dummy variable. The variable is only allowed to have the values 1, 0 or missing. Observations with missing varaibles in the grpdummy are ignored by this command.{p_end}"
				error _rc
			}

			**********
			**Exclude obs with missing value in groupdummy

			*Count number of obs to be dropped and and output that number if more than zero
			count if missing(`grpdummy')
			if `r(N)' > 0 {

				*Prepare the local to be outputted with info on observations excluded
				local obsexcludstring  "`obsexcludstring'`r(N)' observation(s) were excluded due to missing value in  grpdummy(`grpdummy').{break}"
			}

			*Drop obs with missing value in groupvar
			drop if missing(`grpdummy')

		********************************
		*
		*	Checking match continous var
		*
		********************************

			*Test that the continous is numeric
			cap confirm numeric variable `matchvar'
			if _rc != 0 {

				noi di as error "{pstd}The variable to match on specified in matchvar(`matchvar') is not a numeric variable.{p_end}"
				error 109
			}

			**All variables with value 1 or 0 in the group dummy and
			* not excluded by if/in must have a value in matchvar
			count if missing(`matchvar')
			if `r(N)' > 0 {

				*Prepare the local to be outputted with info on observations excluded
				local obsexcludstring  "`obsexcludstring'`r(N)' observation(s) were excluded due to missing value in matchvar(`matchvar').{break}"
			}

			*Drop obs with missing values in match var
			drop if missing(`matchvar')

		********************************
		*
		*	Checking match var and group dummy are unique
		*
		********************************

			if "`seedok'" == "" {

				**test that there are no duplicates in match
				* var within each type of observation
				cap isid `matchvar' `grpdummy'

				if _rc != 0 {

					*Output the error message
					noi di as error "{pstd}There are base observations or target observations {...}"
					noi di as error "with duplicate values in matchvar(`matchvar'). To guarantee {...}"
					noi di as error "a replicable match you must {help seed:set a seed}. To supress {...}"
					noi di as error "this error message after you have set a the seed, or if a {...}"
					noi di as error "replicable match is not important to you, use option {inp:seedok}{p_end}"
					error 198

				}
			}

		********************************
		*
		*	Checking that there are more target
		*	obs than base obs in a 1-to-1 match
		*
		********************************

			if "`m1'" == "" {

				*Count number of base vars
				count if `grpdummy' == 1
				local numBaseObs `r(N)'

				*Count number of target vars
				count if `grpdummy' == 0
				local numTrgtObs `r(N)'

				*Test that there are more target
				cap assert `numTrgtObs' >= `numBaseObs'

				if _rc != 0 {

					noi di as error "{pstd}There are more base observations than target observations. This is not allowed in a one-to-one match. See option {inp:m1} for an alternative matching where it is allowed to have more base observations than target ovbservations.{p_end}"
					error _rc
				}
			}

		********************************
		*
		*	Checking that matchCount is only used with
		*	many-to-one matching
		*
		********************************
		noi di "A1"

		if "`m1'" == "" & "`maxmatch'" != "" {

			noi di as error "{pstd}The option {inp:maxmatch()} can only be used when option {inp:m1} is used, as restricting to a maximum number of matches is only applicable in a many-to-one match.{p_end}"
			error 198
		}
		noi di "A1"

		********************************
		*
		*	Output exclude string
		*
		********************************

			*The exclude string is created above but only displayed
			*after all testing of input is done.

			if "`obsexcludstring'" != "" {

				noi di ""
				noi di "{hline}"
				noi di ""
				noi di "{pstd}{ul:Observations are excluded from the matching for the following reasons:}{break}"
				noi di "`obsexcludstring'{p_end}"

			}

	********************************
	*	Start matching
	********************************

		********************************
		*
		*	Creating tempvar used in matching
		*
		********************************

		*Initiate the temporary variables used by this command
		tempvar prefID prefDiff matched matchcount maxmatchdiff

		gen `prefDiff' 		= .
		gen byte `matched' 	= 0

		*Allow the ID var used to be string
		if `IDtypeNumeric' == 1 {
			gen  `prefID' = .
		}
		else {
			gen  `prefID' = ""
		}

		*Gen a variable that indicates for target vars if the max match is reached
		gen `matchcount' 	= .
		gen `maxmatchdiff' 	= .

		** Generate the inverse of the matchvar to sort descending (gsort is too slow),
		*  a random var to seperate two values with the same match var, and the inverse
		*  of the random var for when sorting descending.
		tempvar rand invsort invrand

		sort `matchvar'
		gen  `invsort' = -1 * `matchvar'

		gen    `rand' = uniform()
		gen `invrand' = -1 * `rand'

		***********
		*Tempvars for matching

		*Diffvars, they are always numeric
		tempvar					 diffup   diffdo   valUp_0   valDo_0   valUp_1   valDo_1
		local 	 updownTempVars `diffup' `diffdo' `valUp_0' `valDo_0' `valUp_1' `valDo_1'

		foreach tempVar of local updownTempVars {

			gen `tempVar' = .
		}

		*ID vars, allowed to be both numeric and string
		tempvar					  	IDup   IDdo   IDup_0   IDdo_0   IDup_1   IDdo_1
		local 	 updownIDTempVars  `IDup' `IDdo' `IDup_0' `IDdo_0' `IDup_1' `IDdo_1'

		foreach tempVar of local updownIDTempVars {

			*Allow the ID var used to be string
			if `IDtypeNumeric' == 1 {
				gen  `tempVar' = .
			}
			else {
				gen  `tempVar' = ""
			}
		}

		***************************
		*
		*	One to one match
		*
		***************************

		if "`m1'" == "" {

			*Start outputting the countdown
			noi di ""
			noi di "{hline}{break}"
			noi di "{pstd}{ul:Matching one-to-one. Base observations left to match:}{p_end}"

			*Create local to display "obs left to match" and to use in while loop
			count if `grpdummy' == 1 & `matched' == 0
			local left2Match = `r(N)'
			noi di "{pstd}`left2Match' " _c

			*Match until no more observations to match.
			while (`left2Match' > 0) {

				**For all observations still to be matched, assign the preferred
				* match among the other unmatched observations
				qui updatePrefDiffPreffID `prefID' `prefDiff' `matchvar' `invsort' `idvar' `grpdummy' `matched' `rand' `invrand' `updownTempVars' `updownIDTempVars'

				*Restrict matches to within maxdiff() if that option is used.
				if "`maxdiff'" != "" {

					*Omit base observation from matching if diff is to big
					replace `matched' 			= 1		if `prefDiff' > `maxdiff' & `grpdummy' == 1

					*Indicate in result var that this obs did not have valid match within maxdiff()
					replace `matchResultName' 	= .d 	if `prefDiff' > `maxdiff' & `grpdummy' == 1

					*Removed preferred match
					if `IDtypeNumeric' == 1 {
						*IDvar is numeric
						replace `prefID'		= .		if `prefDiff' > `maxdiff'
					}
					else {
						*IDvar is string
						replace `prefID'		= ""	if `prefDiff' > `maxdiff'
					}
				}

				*If two observations mutually prefer each other, then indicate both of them as matched.
				replace `matched' = 1 if `matched' == 0 & `prefID' == `idvar'[_n-1] & `prefID'[_n-1] == `idvar'
				replace `matched' = 1 if `matched' == 0 & `prefID' == `idvar'[_n+1] & `prefID'[_n+1] == `idvar'

				*Update local to display "obs left to match" and to use in while loop
				count if `grpdummy' == 1 & `matched' == 0
				local left2Match = `r(N)'
				noi di "`left2Match' " _c

			}

			*End formatting for the "base obs left to match"
			noi di "{p_end}" _c
		}
		***************************
		*
		*	Many to one match with no restriction on # matches
		*
		***************************
		else if "`maxmatch'" == ""  {

			*Start outputting the countdown
			noi di ""
			noi di "{hline}{break}"
			noi di "{pstd}{ul:Matching many-to-one.}{p_end}"

			**For all observations to be matched, assign the preferred
			* match among the other unmatched observations
			updatePrefDiffPreffID `prefID' `prefDiff' `matchvar' `invsort' `idvar' `grpdummy' `matched' `rand' `invrand' `updownTempVars' `updownIDTempVars'

			*Restrict matches to within maxdiff() if that option is used.
			if "`maxdiff'" != "" {

				*Indicate in result var that this obs did not have valid match within maxdiff()
				replace `matchResultName' 	= .d 	if `prefDiff' > `maxdiff' & `grpdummy' == 1

				*Removed preferred match
				if `IDtypeNumeric' == 1 {
					*IDvar is numeric
					replace `prefID'		= .		if `prefDiff' > `maxdiff'
				}
				else {
					*IDvar is string
					replace `prefID'		= ""	if `prefDiff' > `maxdiff'
				}
			}

			*Assign it's own ID as pref ID for all target vars
			replace `prefID'			=  `idvar' if `grpdummy' == 0

			* Replace the _matchCount var with number of base observations in each
			* match group. Each group is all base observation plus the target
			* observation, therefore (_N - 1)
			bys 	`prefID' 			:   replace `matchCountName' = _N - 1 if !missing(`prefID')

			**Replace prefID to missing for target obs that had no base
			* obs matched to it. T
			if `IDtypeNumeric' == 1 {
				*IDvar is numeric
				replace `prefID'		= .		if `matchCountName' == 0
			}
			else {
				*IDvar is string
				replace `prefID'		= ""	if `matchCountName' == 0
			}

			*Only target obs with base obs prefering it are matched
			replace	 `matched' 			= 1		if `matchCountName' != 0

			*Remove values for target obs that were not matched
			replace  `matchCountName'	= . 	if `matchCountName' == 0

		}
		***************************
		*
		*	Many to one match with restriction on # matches
		*
		***************************
		else {

			*Start outputting the countdown
			noi di ""
			noi di "{hline}{break}"
			noi di "{pstd}{ul:Matching many-to-one.}{p_end}"

			*Create local to display "obs left to match" and to use in while loop
			count if `grpdummy' == 1 & `matched' == 0
			local left2Match = `r(N)'
			//noi di "{pstd}`left2Match' " _c

			*Match until no more observations to match.
			while (`left2Match' > 0) {

				**For all observations to be matched, assign the preferred
				* match among the other unmatched observations
				updatePrefDiffPreffID `prefID' `prefDiff' `matchvar' `invsort' `idvar' `grpdummy' `matched' `rand' `invrand' `updownTempVars' `updownIDTempVars'

				*Restrict matches to within maxdiff() if that option is used.
				if "`maxdiff'" != "" {

					*Indicate in result var that this obs did not have valid match within maxdiff()
					replace `matchResultName' 	= .d 	if `prefDiff' > `maxdiff' & `grpdummy' == 1

					*Removed preferred match
					if `IDtypeNumeric' == 1 {
						*IDvar is numeric
						replace `prefID'		= .		if `prefDiff' > `maxdiff'
					}
					else {
						*IDvar is string
						replace `prefID'		= ""	if `prefDiff' > `maxdiff'
					}
				}

				*Assign it's own ID as pref ID for all target vars
				replace `prefID'			=  `idvar' if `grpdummy' == 0

				noi di 1
				sort `prefID' `grpdummy' `prefDiff' `rand'

				by `prefID' : replace `matchcount' = _N if  `matchResultName' 	!= .d

				by `prefID' : replace `matched' 	 = 1 				if `grpdummy' == 0 & `matchcount' >= (`maxmatch'+1)
				by `prefID' : replace `matched' 	 = 1 				if `grpdummy' == 1 & _n <= (`maxmatch'+1) & `matchResultName' != .d

				cap drop `maxmatchdiff'
				by `prefID' : egen 	  `maxmatchdiff' = max(`prefDiff') 	if `matchcount' > 1 & `matchResultName' != .d
				di 3

				**Replace prefID to missing for target obs that had no base
				* obs matched to it. T
				if `IDtypeNumeric' == 1 {
					*IDvar is numeric
					replace `prefID'		= .		if `matchcount' 	 == 1 & `grpdummy' == 0
				}
				else {
					*IDvar is string
					replace `prefID'		= ""	if `matchcount' 	 == 1 & `grpdummy' == 0
				}

				noi tab `matchcount', m

				*pause

				*Remove values for target obs that were not matched
				//replace  `matchCountName'	= . 	if `matchCountName' == 0

				*Update local to display "obs left to match" and to use in while loop
				count if `grpdummy' == 1 & `matched' == 0
				local left2Match = `r(N)'
				noi di "`left2Match'" _c

				count if `grpdummy' == 0 & `matched' == 0
				if `r(N)' == 0 {
					noi di "No more target obs to match"
					local left2Match = 0

					replace `matchResultName' 	= .t 	if `grpdummy' == 1 & `matched' == 0
				}

			}

			pause
			bys `prefID' `matched' : replace `matchCountName' = _N - 1 if  `matched' 	== 1 &  _N > 1

			*End the outputted count down on how many observations left to match
			noi di "{p_end}" _c

		}

		*Update all return vars
		replace `matchDiffName' 	= `prefDiff'	if `matched' == 1
		replace `matchIDname' 		= `idvar' 		if `matched' == 1 & `grpdummy' == 0
		replace `matchIDname' 		= `prefID' 		if `matched' == 1 & `grpdummy' == 1

		*Remove the best match value in obs that did not have a match within maxdiff()
		replace `matchDiffName'  = . 				if `matchResultName' == .d

		*Matched observations are give value 1 in result var
		replace `matchResultName' = 1 				if `matched' == 1 & `matchResultName' != .d

		*Target obs not used
		replace `matchResultName' = 0 if `matched' == 0 & `grpdummy' == 0

		*only keep output vars
		keep `matchIDname' `matchDiffName' `originalSort' `matchResultName' `matchCountName'

		*Merge the results back to the original data set
		tempfile mergefile
		save 	`mergefile'

	restore

	***************************
	*
	*	Merge match results to
	*	original data and assign
	*	remaining missing values
	*	to the result var
	*
	***************************

	*Merge the results with the original data
	tempvar mergevar
	merge 1:1  `originalSort' using `mergefile', gen(`mergevar')

	*remaining missing values are listed in ascending order of importance.
	*Meaning that if a variable is both .m and .i then it will be .i as it
	*is assigned afterwards below.

	*Missing matching var
	replace `matchResultName' = .m if missing(`matchvar')

	*Msising dummy var
	replace `matchResultName' = .g if missing(`grpdummy')

	*Excluded in if/in
	if "`if'`in'" != "" {

		tempvar  ifinvar
		gen 	`ifinvar' = 1 `if'`in'
		replace `matchResultName' = .i if `ifinvar' != 1
	}

	*comress the variables generated
	compress  `matchIDname' `matchDiffName' `matchResultName' `matchCountName'

	*Output result table
	noi outputTable `matchResultName' `grpdummy'

	*Restore the oridinal sort
	sort `originalSort'

}

end

	*Check manually entered names for the return vars.
	cap program drop 	iematchMatchVarCheck
		program define 	iematchMatchVarCheck  , rclass

		args defaultName replace_used userName

		if "`defaultName'" == "_matchID" 		local optionName matchidname
		if "`defaultName'" == "_matchDiff" 		local optionName matchdiffname
		if "`defaultName'" == "_matchResult" 	local optionName matchresult
		if "`defaultName'" == "_matchCount" 	local optionName matchcount

		*All the default names
		local dfltNms _noMatchReason _matchDiff _matchResult _matchCount

		*The other two default names
		local othDfltNms : list dfltNms - defaultName

		*Creating two locals with the deafult name in each local
		local Oth1 : word 1 of `othDfltNms'
		local Oth2 : word 2 of `othDfltNms'
		local Oth3 : word 3 of `othDfltNms'

		*Testing that the option name is not the same as the other variable's default name.
		if ("`userName'" == "`Oth1'" | "`userName'" == "`Oth2'" | "`userName'" == "`Oth3'" | "`userName'" == "_ID")  {

			noi di as error "{pstd}The new name specified in `optionName'(`userName') is not allowed to be _ID, `Oth1', `Oth2', or `Oth3'{p_end}"
			error 198
		}

		*Test if name is set manually
		if "`userName'" != "" {
			*Use the manually set name
			local validMatchVarname `userName'
		}
		else {
			*No manually set name, use deafult name
			local validMatchVarname `defaultName'
		}

		*Make sure that the manually entered name is not already used
		cap confirm variable `validMatchVarname'
		if _rc == 0 {

			if `replace_used' == 1 {
				//Replace is used, drop the old var
				drop `validMatchVarname'
			}
			else {

				*Replace is not used. Prepare an error message and throw error

				if "`userName'" != "" {
					*Error message for user specified name s
					local nameErrorString "The variable name specified in `optionName'(`userName')"
				}
				else {
					*Error message for user specified name s
					local nameErrorString "A variable with name `validMatchVarname'"
				}

				*Trow error
				noi di as error "{pstd}`nameErrorString' is already defined in the data set. Either drop this variable, use the replace option or specify a another variable name using `optionName'()."
				error 110

			}
		}

		*Testing that the new name is valid by creating a variable that is dropped immedeatly afterwards
		cap gen `validMatchVarname' = .

		if _rc != 0 {

			noi di as error "{pstd}The variable name specified in `optionName'(`userName') is not a valid variable name."
			error _rc
		}
		drop `validMatchVarname'

		return local validVarName 	"`validMatchVarname'"

	end

	** This function is called to assign the preferred match for all unmatched
	*  observations to any other unmatched observation. Returns a variable pref that is the
	cap program drop 	updatePrefDiffPreffID
		program define 	updatePrefDiffPreffID

		args prefID prefDiff matchvar invsort idvar grpvar matched rand invrand diffup diffdo valUp_0 valDo_0 valUp_1 valDo_1 IDup IDdo IDup_0 IDdo_0 IDup_1 IDdo_1

		*****************
		*Update possible matches with higher rank value
		sort `matched' `matchvar' `rand'

		updateBestValID 0 `matchvar' `idvar' `grpvar' `matched' `valUp_0' `IDup_0'
		updateBestValID 1 `matchvar' `idvar' `grpvar' `matched' `valUp_1' `IDup_1'

		*****************
		*Update possible matches with lower rank value
		sort `matched' `invsort' `invrand'

		updateBestValID 0 `matchvar' `idvar' `grpvar' `matched' `valDo_0' `IDdo_0'
		updateBestValID 1 `matchvar' `idvar' `grpvar' `matched' `valDo_1' `IDdo_1'

		*****************
		*Create one varaible common for both groups with diff upwards
		replace `diffup' 	= abs(`matchvar' - `valUp_1') if `grpvar' == 1
		replace `diffup' 	= abs(`matchvar' - `valUp_0') if `grpvar' == 0

		*Create one varaible common for both groups with diff downwards
		replace `diffdo' 	= abs(`matchvar' - `valDo_1') if `grpvar' == 1
		replace `diffdo' 	= abs(`matchvar' - `valDo_0') if `grpvar' == 0

		*Create one varaible common for both groups with ID upwards
		replace `IDup' 		= `IDup_1' 	if `grpvar' == 1
		replace `IDup' 		= `IDup_0' 	if `grpvar' == 0

		*Create one varaible common for both groups with ID downwards
		replace `IDdo' 		= `IDdo_1' 	if `grpvar' == 1
		replace `IDdo' 		= `IDdo_0' 	if `grpvar' == 0

		replace `prefID' 	= `IDdo' 	if `matched' == 0 & `diffdo' <= `diffup'
		replace `prefID' 	= `IDup' 	if `matched' == 0 & `diffdo' >  `diffup'

		replace `prefDiff' 	= `diffdo' 	if `matched' == 0 & `diffdo' <= `diffup'
		replace `prefDiff' 	= `diffup' 	if `matched' == 0 & `diffdo' >  `diffup'

	end

	** This function goes through the observatioins from top to down and copying
	*  the match value of the closest observation of the other group above to
	*  (bestVal) and the ccoprresponding ID to (bestID) for obe group at the time.
	*  To go from bottuom to top sort with invsort and apply this command.
	cap program drop 	updateBestValID
		program define 	updateBestValID

		args grpvl matchval idvar grpvar matched bestVal bestID

		*Test if ID var is string or numeric
		local IDNumeric 0
		cap confirm numeric variable `idvar'
		if _rc == 0 local IDNumeric 1

		*Reset all values
		replace `bestVal' 	= .
		if `IDNumeric' == 1 replace `bestID' 	= .
		if `IDNumeric' == 0 replace `bestID' 	= ""

		*Set the match value and ID of observations that are in the other group
		replace `bestVal'   = `matchval' 		if `grpvar' != `grpvl' & `matched' == 0
		replace `bestID'  	= `idvar' 			if `grpvar' != `grpvl' & `matched' == 0

		*Fill in that value from the observation in the other group until getting to another observation of the other group
							replace `bestVal'   = `bestVal'[_n-1]	if `bestVal' == .  & `matched' == 0
		if `IDNumeric' == 1 replace `bestID'  	= `bestID'[_n-1] 	if `bestID'	 == .  & `matched' == 0
		if `IDNumeric' == 0 replace `bestID'  	= `bestID'[_n-1] 	if `bestID'	 == "" & `matched' == 0

	end

	** This function creates the output table.
	cap program drop 	outputTable
		program define 	outputTable

		qui {
			args resultVar grpdum

			*List the texts used in the first column in the
			local text_1 " 1 Matched"
			local text_0 " 0 Not matched"
			local text_d ".d No match within maxdiff()"
			local text_i ".i Excluded using if/in"
			local text_g ".g Missing grpdummy()"
			local text_m ".m Missing matchvar()"
			local text_t ".t No more target obs"

			*The minimum width of the
			local firstColWidth = max(strlen(" `resultVar'") , strlen(" value and result"))

			levelsof `resultVar' , missing local(resultsUsed)

			foreach result of local resultsUsed {

				*Remove the . from the local to match the string
				local result = subinstr("`result'",".","",1)

				* Test if the text in the first column is longer
				* for this row than previous row
				local firstColWidth = max(`firstColWidth' , strlen("`text_`result''"))
			}

			* Create a local that indicates if there is column
			* for obs with missing value in tmt dummy
			local missingGrpDum 0
			count if missing(`grpdum')
			if `r(N)' > 0 local missingGrpDum 1

			*Set all locals that determins column width

			local C1 "{col 4}{c |}"

			di "`firstColWidth'"

			local col1width = `firstColWidth'  + 1
			local hli1 "{hline `col1width'}"
			local cen1 "{center `col1width':"

			local col2border = `firstColWidth' + 6
			local C2  "{col `col2border'}{c |}"
			local C2a "{col `col2border'}"

			local col3border = `firstColWidth' + 17
			local C3 "{col `col3border'}{c |}"

			local col4border = `firstColWidth' + 30
			local C4 "{col `col4border'}{c |}"

			local grpdumCentre 23 //Overspills automatically

			local lastT  	"{c RT}"
			local lastTdown	"{c RT}"
			local lastC  	"{c BRC}"

			if `missingGrpDum' {

				local lastT 		"{c +}{hline 9}{c RT}"
				local lastTdown 	"{c BT}{hline 9}{c RT}"
				local lastC 		"{c BT}{hline 9}{c BRC}"
				local missTitle 	"  missing "
				local grpdumCentre 	33

			}

			noi di ""
			noi di ""
			noi di "{hline}"
			noi di ""
			noi di "{pstd}{ul:Output of Matching Result:}{p_end}"
			noi di ""
			noi di "{col 5}`cen1'`resultVar'}`C2a' {centre `grpdumCentre':`grpdum' }"
			noi di "{col 4}{c LT}`hli1'{c +}{hline `grpdumCentre'}{c RT}"
			noi di "`C1'`cen1'value and result}`C2' 1 (base)   0 (target) `missTitle'{c |}"
			noi di "{col 4}{c LT}`hli1'{c +}{hline 10}{c +}{hline 12}`lastT'"

			*This is the roworder for the output table
			local resultTableOrder 1 0 .d .t .i .g .m

			foreach result of local resultTableOrder {

				*Test if this result was used
				if `:list result in resultsUsed' {

					*Count base observations in this result type
					qui count if `resultVar' == `result' & `grpdum' == 1
					local numBase = trim("`: display %16.0gc  `r(N)''")

					*Count target observations in this result type
					qui count if `resultVar' == `result' & `grpdum' == 0
					local numTarg = trim("`: display %16.0gc  `r(N)''")

					*Count observations that are neither base or target in this result type
					if `missingGrpDum' {

						qui count if `resultVar' == `result' & missing(`grpdum')
						local numMiss = trim("`: display %16.0gc  `r(N)''")

						local missCol "{ralign 9 :`numMiss' }{c |}"

					}

					*Prepare the local that displays the columns with numbers
					local numCols "`C2'{ralign 10 :`numBase' }`C3'{ralign 12 :`numTarg' }`C4'`missCol'"

					*Remove the . from the local to match the string
					local result = subinstr("`result'",".","",1)

					*Output the table row
					noi di "`C1'`text_`result''`numCols'"

				}
			}

			*Output line before N per group row
			noi di "{col 4}{c LT}`hli1'{c +}{hline 10}{c +}{hline 12}`lastT'"

			*Caculate N per group row for base observations
			qui count if `grpdum' == 1
			local numBase = trim("`: display %16.0gc  `r(N)''")

			*Caculate N per group row for target observations
			qui count if `grpdum' == 0
			local numTarg = trim("`: display %16.0gc  `r(N)''")

			*Caculate N per group row for observations neither base or target
			if `missingGrpDum' {

				qui count if missing(`grpdum')
				local numMiss = trim("`: display %16.0gc  `r(N)''")

				local missCol "{ralign 9 :`numMiss' }{c |}"

			}

			*Output N per group row
			noi di "`C1'`cen1'N per group}`C2'{ralign 10 :`numBase' }`C3'{ralign 12 :`numTarg' }`C4'`missCol'"

			*Output line before total N row
			noi di "{col 4}{c LT}`hli1'{c +}{hline 10}{c BT}{hline 12}`lastTdown'"

			*Count total N
			qui count
			local numTot = trim("`: display %16.0gc  `r(N)''")

			*Output total N row
			noi di "`C1'`cen1'Total N}`C2'{centre `grpdumCentre':`numTot'}`C4'"

			*Output bottom line
			noi di "{col 4}{c BLC}`hli1'{c BT}{hline `grpdumCentre'}{c BRC}"
		}
	end

error: pathspec 'src/ado_files/iematch.do' did not match any file(s) known to git


Help file initial commit

Help file initial commit

Help file initial commit

{smcl}
{* 26 Dec 2016}{...}
{hline}
help for {hi:iegraph}
{hline}

{title:Title}

{phang2}{cmdab:iematch} {hline 2} Matching base observations towards target observations using on a single continous variable.

{title:Syntax}

{phang2}
{cmdab:iematch} {ifin}
, {cmdab:grp:dummy(}{it:varname}{cmd:)} {cmdab:match:var(}{it:varname}{cmd:)}
[{cmdab:id:var(}{it:varlist}{cmd:)} {cmdab:m1} {cmdab:maxdiff(}{it:numlist}{cmd:)} {cmd:seedok}
{cmdab:matchid:name(}{it:string}{cmd:)} {cmdab:matchdi:ffname(}{it:string}{cmd:)}
{cmdab:matchre:sultname(}{it:string}{cmd:)} {cmdab:matchco:untname(}{it:string}{cmd:)}
]

{marker opts}{...}
{synoptset 22}{...}
{synopthdr:options}
{synoptline}
{synopt :{cmdab:grp:dummy(}{it:varname}{cmd:)}}The group dummy variable where 1
	indicates base observations and 0 target observations{p_end}
{synopt :{cmdab:match:var(}{it:varname}{cmd:)}}The variable with a continous value
	to match on{p_end}
{synopt :{cmdab:id:var(}{it:varlist}{cmd:)}}The uniquely and fully identifying ID
	varaible. Used to indicate which target observation a base observation is match
	with. If omitted an ID variable will be created.{p_end}
{synopt :{cmdab:m1}}Allows many-to-one matches. The default is to allow only
	one-to-one matches. See the {help iematch##desc:description} section.{p_end}
{synopt :{cmdab:maxdiff(}{it:numlist}{cmd:)}}Set a maximum difference allowed in
	{cmdab:matchvar()}. If a base observation has no match within this difference
 then it will remain unmatched{p_end}
{synopt :{cmd:seedok}}Supresses the error maessage thrown when there are duplicates
	in {cmd:matchvar()}. When there are duplicates, the seed needs to be set in order
	to have a replicable match. The {help seed} should be set before this command.{p_end}
{synopt :{cmdab:matchre:sultname(}{it:string}{cmd:)}}Manually sets the name of
	the variable that indicates if an observation was matched, or provide a reason why
	it was not. The default is _matchResult{p_end}
{synopt :{cmdab:matchid:name(}{it:string}{cmd:)}}Manually sets the name of the
	variable that indicates which target observation each base observation is
	matched with. The default is _matchID{p_end}
{synopt :{cmdab:matchdi:ffname(}{it:string}{cmd:)}}Manually sets the name of the
	variable that indicates the differnece in {cmdab:matchvar()} in each match
	pair/group. The default is _matchDiff{p_end}
{synopt :{cmdab:matchco:untname(}{it:string}{cmd:)}}Manually sets the name of the
	variable that indicates how many observations a target obsersvation is matched
	with in a many-to-one matches. The default is _matchCount{p_end}
{synoptline}

{marker desc}
{title:Description}

{pstd}{cmdab:iematch} matches base observations towards target observations in terms
	of nearest value in {cmd:matchvar()}. Base observations are observations with
	value 1 in {cmd:grpdummy()} and target observations are observations with value
	0. For example, in a typical p-score match, base observations are treatment and
	target is control, however, there are many other examples of matching where it could
	be different.

{pstd}{cmdab:iematch} bases its matching algorithm on the Stable Marriage algorithm.
	This algorithm was chosen because it always provides a solution and allows stable
	matching even if multiple observations have identical match
	values (see {cmd:seed()} option for more details). One disadvantage of this
	algorithm is that it takes into account local efficiency only, and not global efficiency. This
	means that it is possible that other matching algorithms might generate a more
	efficient match in terms of the sum of the difference of all matched pairs/groups.

{pstd}{hi:{ul:One-to-one matching algorithm}}{break}
	The algorithm used in a one-to-one match starts by evaluating which
	target observation each base observation is closest to and vice versa for each
	target observations. If a base and target observation pair mutually prefer
	each other, then these two observations are matched. The algorithm then repeats
	the initial two evaluation steps, and excludes observations after they are matched,
	until all base observations are either matched or excluded due to the option {cmdab:maxdiff()}.
	Matched observations ends up in pairs of exactly one base observation and one
	target observation.

{pstd}In a one-to-one match, there has to be at least as many target observations
	as there are base observations. A one-to-one match returns three variables. One
	variable indicates the result of the matching for each observation, such as,
	matched, not matched, no match within the max difference, etc. The other two variables
	hold information on the matched pair. One variable is the ID of the target observation
	in the matched pair, and the other variable is the difference in {cmd:matchvar()}
	between the two observations in the match pair. See the below in this section
	for more details on the variables generated.

{pstd}{hi:{ul:Many-to-one matching algorithm}}{break}
	The algorithm used for many-to-one matching is the same as in a one-to-one match. But instead
	of matching only when there is a mutual preference, all base observations are
	matched towards their preferred target observation in the first step, as long
	as the match is within the max-value if {cmdab:maxdff()} is used. Matched observations
	end up in groups in which there is exactly one target observation but where there are
	either one or several base observations.

{pstd}In a many-to-one match, there is no restriction in terms of the number of
	base observations in relation to target observations. The many-to-one matching
	yields four variables. Three of the variables are the same as in one-to-one
	matching, and only the variable listing the difference  The fourth variable indicates how many base observations that were matched
	towards each target observation. See the below in this section for more details on
	the variables generated.

{pstd}{hi:{ul:Variables generated}}{break}
	This section explains the variables that are generated by this command. All variables
	will be referred to by their default names, but those names can be manually set to somthing
	else (see the options for this command).

{pstd}{hi:_matchResult}{break}
	This variable indicates the result of the match for all observations. Observations
	that ended up in a match pair/group has the value 1. Target observations not matched have the
	value 0. Base observations without a valid match due to {cmdab:maxdff()} are
	assigned the value .d. Observations excluded from the match using {inp:if}/{inp:in} are
	assigned the value .i. Observations excluded from the match due to missing value in {cmd:grpdummy()} are
	assigned the value .g. Observations excluded from the match due to missing value in {cmd:matchvar()} are
	assigned the value .m. All values have descreptive value labels.

{pstd}{hi:_matchID}{break}
	This variable indicates the ID of the target observations in each match pair/group. For matched
	target observations, the value in _matchID will be equal to the value in the ID
	variable. Since the values in the ID varaible are unique and there is exactly one target
	observation in each matched pair/group, this variable functions as a unique pair/group ID.
	In addition to indicating which observations are included in the same pair/group, this
	varaible can be used to include a pair/group fixed effect in a regression.

{pstd}{hi:_matchDiff}{break}
	This variable indicates the difference in {cmd:matchvar()} between matched base observations
	and target observations. In a one-to-one match this value is the identical for
	both the base observation and the target observation in each matched pair.
	In a many-to-one match, this value is only indicated for base observations. It is
	missing for target observations as there are potentially multiple matches, and
	subsequently multiple differences.

{pstd}{hi:_matchCount}{break}
	In a many-to-one match, this variable indicates how many base observations were
	matched towards each matched target observation. This variable can be used as regression
	weights when controlling for the fact that some observations are matched towards multiple
	observations.

{marker optslong}
{title:Options}

{phang}{cmdab:grp:dummy(}{it:varname}{cmd:)} is the dummy variable that indicates if an observation
	is a base or target observation. This variable, must be numeric and is only allowed to have
	the values 1, 0 or missing. 1 indicates a base observation, 0 indicates a target observation,
	and observations with a missing value will be excluded from the matching.

{phang}{cmdab:match:var(}{it:varname}{cmd:)} is the variable used to compare observations when
	matching. This must be a numeric variable, and it is typically a continuous
	variable. Observations with a missing value will be excluded from the matching.

{phang}{cmdab:id:var(}{it:varlist}{cmd:)} indicates the variable that uniquely
	and fully identifies the data set. The values in this variable is the values
	that will be used in the variable that indicates which target observation each
	base observations matched against. If this option is omitted, a variable called
	_ID will be generated. The observation in the first row is given the value 1,
	the second row value 2 and so fourth.

{phang}{cmdab:m1} sets the match to a many-to-one match (see {help iematch##desc:description}).
	This allows multiple base observations to be matched towards a single target observation.
	The default is the one-to-one match where a maximum one base observation is matched towards
	each target observation. This option allows the number of base observations
	to be larger then the number of target observations.

{phang}{cmdab:maxdiff(}{it:numlist}{cmd:)} sets a maximum allowed difference between
	a base observation and a target observation for a match to be valid. Any base
	observation without a valid match within this difference will end up unmatched.

{phang}{cmd:seedok} supresses the error message throwned when there are duplicates among
	the base observations or the target observations in {cmd:matchvar()}. When there
	are duplicates a random variable is used to distinguish which variable to match.
	Setting the seed makes this randomization replicable and thereby making the matching
	also replicable. The {help seed} should be set before this command by the user. When the
	seed is set, or if replicable matching is not important, then the option {cmd:seedok} can
	be used to supress the error message. Duplicate pairs where one observation is a base
	observation and the other is a target observations are allowed.

{phang}{cmdab:matchre:sultname(}{it:string}{cmd:)} manually sets the
	name of the variable that reports the matching result for each observation.
	If omitted, the default name is {inp:_matchResult}. The names {inp:_ID},
	{inp:_matchID}, {inp:_matchDiff} and {inp:_matchCount} are not allowed.

{phang}{cmdab:matchid:name(}{it:string}{cmd:)} manually sets the
	name of the variable that list the ID of the target observations in each match pair/group.
	If omitted, the default name is {inp:_matchID}. The names {inp:_ID}, {inp:_matchDiff}, {inp:_matchResult}
	and {inp:_matchCount} are not allowed.

{phang}{cmdab:matchdi:ffname(}{it:string}{cmd:)} manually sets the name of the variable
	that indicates the difference between the matched base observations
	and target observations. If omitted, the default name is {inp:_matchDiff}. The
	names {inp:_ID}, {inp:_matchID}, {inp:_matchResult} and {inp:_matchCount} are
	not allowed.

{phang}{cmdab:matchco:untname(}{it:string}{cmd:)} manually sets the
	name of the variable that indicates the number of base observations that has
	been matched towards each matched matched target observation. This option may
	only be used in combination with option {cmd:m1}. If omitted, the default
	name is {inp:_matchCount}. The names {inp:_ID}, {inp:_matchID}, {inp:_matchDiff}
	and {inp:_matchResult} are not allowed.

{title:Examples}

{pstd} {hi:Example 1.}

{pmore}{inp:iematch , grpdummy({it:tmt}) matchvar({it:p_hat})}

{pmore}In the example above, the observations with value 1 in {it:tmt} will be matched
	towards the nearest, in terms of {it:p_hat}, observations with value 0 in {it:tmt}.

{pstd} {hi:Example 2.}

{pmore}{inp:iematch if {it:baseline} == 1  , grpdummy({it:tmt}) matchvar({it:p_hat}) maxdiff(.001)}

{pmore}In the example above, the observations with value 1 in {it:tmt} will be matched
	towards the nearest, in terms of {it:p_hat}, observations with value 0 in {it:tmt} as
	long as the difference in {it:p_hat} is less than .001. Only observations that has the
	value 1 in variable {it:baseline} will be included in the match.

{title:Acknowledgements}

{phang}I would like to acknowledge the help in testing and proofreading I received in relation to this command and help file from (in alphabetic order):{p_end}
{pmore}Michael Orebvo{break}

{title:Author}

{phang}Kristoffer Bjarkefur & Mrijan Rimal, The World Bank, DECIE

{phang}Please send bug-reports, suggestions and requests for clarifications
		 writing "ietools iegraph" in the subject line to:{break}
		 kbjarkefur@worldbank.org

{phang}You can also see the code, make comments to the code, see the version
		 history of the code, and submit additions or edits to the code through
		 the github repository of ietoolkit:{break}
		 {browse "https://github.com/worldbank/ietoolkit"}

error: pathspec 'iegraph.sthlp' did not match any file(s) known to git


example

example

fatal: unable to access 'https://github.com/sergiocorreia/reghdfe.git/': The requested URL returned error: 403


first commit

first commit

use ${stash}master, clear

local isbaseball `1'
local isbaseball "1"

local var img
keep if isbaseball == `isb'

gen tvar = treat

xtreg `var' tvar##post##quality i.$fe, vce(robust) fe level(90)

qui parmest, label list(parm estimate min* max* p) saving(${stash}pars_tmp, replace) level(90)

clear
use ${stash}pars_tmp, clear

keep if regexm(parm, "[0-9].*tvar.*post.*quality") == 1
drop if estimate == 0

gen quality = regexs(1) if regexm(parm, ".*post.*\#([0-9]+)\.quality")
list quality estimate max min
gen xaxis = 0
destring quality, replace

graph twoway (bar estimate quality, msize(small) lpattern(solid) lcolor(edkblue) lwidth(thin) barwidth(0.08)) (rcap min max quality), legend(off) title("") xtitle("")

graph export "${tables}quality_`var'_`isbaseball'.eps", replace

shell epstopdf  "${tables}quality_`var'_`isbaseball'.eps"

end

error: pathspec 'scripts/stata/ado/chart_qual.ado' did not match any file(s) known to git


Added -matawarn-.

Added -matawarn-.

pr matawarn, rclass
	vers 10.1

	syntax anything(name=fn id=filename), [View]

	gettoken fn rest : fn
	if `:length loc rest' {
		di as err "invalid filename"
		ex 198
	}
	qui findfile `"`fn'"'
	loc fn "`r(fn)'"

	if !c(noisily) {
		di as err "quietly not allowed"
		ex 198
	}

	loc log _matawarn
	cap log close `log'
	tempfile res
	qui log using `res', name(`log') s

	clear programs
	clear mata
	do `"`fn'"'

	qui log close `log'

	preserve

	qui infix str line 1-244 using `res', clear

	qui cou if regexm(line, "^{txt}note: ")
	if r(N) {
		if "`view'" == "" ///
			di as txt _n "Warning(s) were issued."
		else {
			qui copy `res' matawarn_results.smcl, replace
			view matawarn_results.smcl
		}

		ret sca warn = 1
	}
	else {
		di as txt _n "No warnings were issued."
		ret sca warn = 0
	}
end

error: pathspec 'cscript/matawarn.ado' did not match any file(s) known to git


Add WBOPRT08 modelsim script.

Add WBOPRT08 modelsim script.

# Xilinx WebPack modelsim script
#
# cd C:/workspace/zpu/zpu/hdl/example_medium
# do simzpu_medium.do

set BreakOnAssertion 1
vlib zpu

vcom -work zpu ../vhdl/zpu_pkg.vhdl
vcom -work zpu ../vhdl/wishbone.vhdl

vlib wb_slaves
vcom -work wb_slaves ../vhdl/wb_slaves/wb_slaves_pkg.vhdl
vcom -work wb_slaves ../vhdl/wb_slaves/WBOPRT08.vhdl

vlib work
vcom -work work ../vhdl/testbenches/zpu_wishbone_WBOPRT08.vhdl

# run ZPU
vsim zpu_wishbone_WBOPRT08_tb

view wave

add wave -recursive *
configure wave -timelineunits us

#add wave -recursive *
view structure
#view signals

# Enough to run tiny programs
run 1000 ms

error: pathspec 'sim/zpu_wishbone_WBOPRT08.do' did not match any file(s) known to git