*! version 2.0 <25Feb2005>
*! implements Hosmer & Lemeshow's method of quartile design variables to check linearity in the link function of a continuous covariate
*! author: Alex Gamma, Zurich (gamma@bli.unizh.ch)


#delimit ;
version 8;
capture program drop lincheck;

program define lincheck;

tempvar med b q;
capture clonevar `q'=quartile; /* should a var named "quartile" already exist in the data set, temporarily save it*/
capture drop quartile;

local cmd "`0'";		/*extract the user's estimation command*/
if "`cmd'"=="" {;
	display as error "no argument given; {cmd:lincheck} must be followed by an estimation command";
	exit;
};

if substr("`cmd'",1,2)=="xi" {;
	local xi "";
	gettoken dump vl : cmd, parse(":");
	gettoken dump vl : vl, parse(":");
	gettoken dump vl : vl; 			/* "xi...:" and command-name are now stripped off of user input */
};
else if word("`cmd'",1)=="by" | word("`cmd'",1)=="bysort" {;
	display as error "by and bysort not allowed";
	exit;
};
else {;
	local xi "xi:";
	gettoken dump vl : cmd; 			/* "xi...:" and command-name are now stripped off of user input */
};

quietly `cmd';

capture local preds: colnames e(V); 						/*get names of predictors of previous regression from variance-covariance matrix */
if _rc > 0 {;
	display as error "matrix e(V) not found: the estimation command you typed after {cmd:lincheck} is not suitable for {cmd:lincheck}";
	exit;
};
local contvar = word("`preds'",1);		/*extracting from e(V) the continuous predictor that is to be tested for linearity */

if word("`vl'",1)=="`e(depvar)'" {;
	local contvar2=word("`vl'",2); 		/* contvar2 contains the first predictor variable from the user input */
};
else {;
	local contvar2=word("`vl'",1);		/* contvar2 contains the first predictor variable from the user input */
};

/* check if first predictor form e(V) matches first predictor as extracted from user input. if not, the predictor has been dropped from the model */
if "`contvar'"!="`contvar2'" display as error "Error: either {cmd:lincheck} does not work with the specified estimation command, or the continous predictor `contvar2' has been dropped
 from the model, in which case {cmd:lincheck} will proceed using the next available variable (`contvar'), although this is most likely not what you wanted.";

quietly xtile quartile =`contvar',nq(4);
quietly sum `contvar',d;
quietly bysort quartile: egen `med'=median(`contvar'); 			/* median of quartiles */

local newcmd = subinword("`cmd'","`contvar'","i.quartile",1);		/* replacing the continuous predictor with the quartile dummies */
display as input "`xi' `newcmd'";
`xi' `newcmd'; 												/* estimating model with quartile dummies replacing continuous predictor */


/* regression coefficients for quartile */
quietly {;
		gen `b'=0 if quartile ==1;
		capture replace `b'=_b[_Iquartile_2] if quartile ==2;
		capture replace `b'=_b[_Iquartile_3] if quartile ==3;			/* if any of the quartile dummies is dropped, don't plot it */
		capture replace `b'=_b[_Iquartile_4] if quartile ==4;
};

twoway (connected `b' `med', sort),ytitle("coefficient") xtitle("`contvar'"); 		/* plot coefs vs. quartile medians */

capture drop _Iquartile*;
drop quartile;
capture clonevar quartile=`q'; /* in case the var "quartile" already existed, restore it*/

end;