* stripolate 
*! 1.1.0 NJC 15dec2016 
* 1.0.0 NJC 14dec2016 
* mipolate 1.2.0 NJC 2sep2015 
* 1.1.0 NJC 27aug2015 
* 1.0.0 NJC 20jul2015 
* ipolate 1.3.3  21sep2004
program stripolate, byable(onecall) sort
	version 10          
	syntax varlist(min=2 max=2) [if] [in], /// 
	GENerate(string) ///
	[ BY(varlist)    /// 
	Forward          ///
	Backward         ///
	Groupwise ]

	// syntax checks 
	tokenize `varlist' 
	args stry x 

	capture confirm string var `stry' 
	if _rc { 
		di as err "{p}stripolate is for interpolation of " ///
		"string variables only: try {cmd:mipolate} (SSC)?{p_end}" 
		exit _rc 
	} 

	capture confirm numeric var `x' 
	if _rc { 
		di as err "{p}stripolate is for interpolation with " ///
		"respect to a numeric variable: see {help stripolate}{p_end}" 
		exit _rc 
	} 

	if _by() {
		if "`by'" != "" {
			di as err /*
			*/ "option by() may not be combined with by prefix"
			exit 190
		}
		local by "`_byvars'"
	}

	local nopts : word count `forward' `backward' `groupwise' 

	if `nopts' != 1 {
		di as err "must specify one interpolation method" 
		exit 198 
	}

	confirm new var `generate'

	quietly {
		// anything to do? 
		marksample touse, novarlist  
		replace `touse' = 0 if missing(`x')
		count if `touse' 
		if r(N) == 0 error 2000 

		count if missing(`stry') & `touse' 
		if r(N) == 0 { 
			noisily di as txt "{p}nothing to do; " /// 
			"no missing `stry' that can be interpolated{p_end}" 
			exit 0 
		} 

		// uniqueness checks  
		tempvar diff z  
		// if we have different strings say "A" "B" for identical `x' 
		// then we don't know which to use 
		
		bysort `touse' `by' `x' (`stry') : ///
			gen byte `diff' = !missing(`stry') & (`stry' != `stry'[_N]) 
		bysort `touse' `by' (`diff'): replace `diff' = `diff'[_N] 
		replace `touse' = 0 if `diff' 

		count if `touse' 
		if r(N) == 0 { 
			local msg "{p}no interpolation: different non-missing string values" 
			if "`by'" != "" { 
				di as err "`msg' for same `by' and `x'{p_end}" 
			}
			else di as err "`msg' for same `x'{p_end}" 
			exit 498 
		} 

		// forward or backward 
		if "`forward'`backward'" != "" { 
			clonevar `z' = `stry' 

			if "`forward'" != "" { 
				bysort `touse' `by' (`x') : ///
				replace `z' = `z'[_n-1] if `touse' & missing(`z' ) 
			}
			else { 
				tempvar negx 
				gen double `negx' = -`x' 
				bysort `touse' `by' (`negx'): /// 
				replace `z' = `z'[_n-1] if `touse' & missing(`z') 
			}
		}

		if "`groupwise'" != "" { 
			// check for uniqueness again 
			// if we have different strings say "A" "B" in any group       
			// then we don't know which to use 
			bysort `touse' `by' (`stry') : ///
				replace `diff' = !missing(`stry') & (`stry' != `stry'[_N]) 
			bysort `touse' `by' (`diff') : replace `touse' = 0 if `diff'[_N] 
			count if `touse' 

			if r(N) == 0 { 
				local msg1 "{p}no interpolation: different non-missing string values" 
				if "`by'" != "" local msg2 " for same `by'" 
				di as err "`msg1'`msg2'{p_end}" 
				exit 498 
			} 
			
			clonevar `z' = `stry' 
			bysort `touse' `by' (`stry') : ///
				replace `z' = `z'[_N] if missing(`z') & `touse'  
		} 

		rename `z' `generate'
		compress `generate' 
		count if missing(`generate') 
	}

	if r(N) > 0 {
		if r(N) != 1 local pl "s" 
		di as txt "(" r(N) `" missing value`pl' generated)"'
	}
end