/* kr20: reliability of a set of dichotomous items Version 1.2 -- Date: September 14th, 1999 By: HervŽ CACI (hcaci@wanadoo.fr) v1.0: Initial release (August 1998) v1.2: Added item-rest point biserial correlation Deleted item-test point biserial correlation Added "sort" option Deleted "total" option Save statistics in global macros S3-S6 */ program define kr20 version 5.0 *! Version 1.2 -- September 14th, 1999 /* Parse standard Stata commands */ local varlist "required existing min(2)" local if "optional" local in "optional" local options "sort(string)" parse "`*'" parse "`varlist'", parse(" ") local nitems : word count `varlist' /* Which sort option ? */ local sortkey = -1 if "`sort'" == "" { local sortkey = 0 } else if substr("`sort'",1,4) == "diff" { local sortkey = 1 } else if substr("`sort'",1,4) == "corr" { local sortkey = 2 } else if substr("`sort'",1,4) == "item" { local sortkey = 3 } else { di in red _n "Bad sort option" exit } /* Here we go... nam.. = Name of the variable d.. = Item difficulty tdiff = Average value of the item difficulties v.. = Item variance n.. = # of observations m.. = # of missing observations totMean= Mean of the total score totSD = Standard deviation of the total score totVar = Variance of the total score r.. = Item-Rest P-B correlation coefficient tcorr = Average value of the item-test pb coefficients tpbcorr= Average value of the item-rest pb coefficients */ tempvar totMean totSD totVar touse local theSum 0 local tdiff 0 local tcorr 0 local tpbcorr 0 /* "If" "in" implementation */ preserve mark `touse' `if' `in' markout `touse' `varlist' quietly drop if `touse'== 0 quietly egen tempTot= rsum(`varlist') quietly summarize `tempTot', detail local totMean= _result(3) local totVar = _result(4) /* First of all, must check whether all variables are dichotomous (i.e. 0/1) */ local i=1 while "`1'" != "" { /* Exit with error if the variable is not an integer variable*/ capture confirm string variable `1' if _rc == 0 { display "Sorry `1' is not a numeric variable..." exit } /* Look for unique values, taking missing values in consideration */ sort `1' quietly by `1': gen long cnt=1 if _n==1 /* Mark first element of each category */ quietly replace cnt=sum(cnt) local uniq=cnt[_N] capture drop cnt capture drop ismiss quietly gen byte ismiss= (`1'==.) quietly count if (`1'==.) local uniq=`uniq'-(_result(1)!=0) local m`i'= _result(1) /* Remember the # of missing obs */ /* Test the dichotomy of the variable */ if `uniq' > 2 { display "`1' has more than two unique values..." exit } local nam`i'="`1'" if `uniq' < 2 { local v`i'=0 /* Item variance is always zero in this case */ quietly count if (`1'!=.) local n`i'=_result(1) /* # of non-missing values */ if `1'[1] ==0 { local d`i'=0 /* When all answers are "wrong", item difficulty is zero */ } else if `1'[1]==1 { local d`i'=1 /* When all answers are "right", item difficulty is one */ local tdiff = `tdiff'+ 1 } else { display "Error: `1' must be 0 or 1" exit } } else { /* There are only 2 categories. Data are still sorted by `1' */ quietly by `1': gen long cnt=_N /* cnt is number of items of each category */ quietly by `1': gen byte first=1 if _n==1 /* mark the first item of each category */ sort first `1' /* Sort: one item of each category */ /* At this point, cnt[1] is number of items "0" cnt[2] is number of items "1" So, check whether items are correctly coded as 0 or 1 */ if `1'[1] != 0 | `1'[2] != 1 { display "`1' must be 0 or 1" exit } local cntitem=cnt[1]+cnt[2] /* # of non-missing 0 or 1 values */ local n`i' = `cntitem' local d`i'= cnt[2]/`cntitem' /* Item difficulty */ local v`i'= `d`i'' * (cnt[1]/`cntitem') /* Item variance */ local tdiff = `tdiff'+ `d`i'' } /* Point biserial correlation coefficient item-rest sMean = Mean score on continuous variable of "successful" group on dichotomous variable uMean = Mean score on continuous variable of "unsuccessful" group on dichotomous variable totSD = Standard deviation of total score */ quietly gen tempTot2=tempTot-`1' quietly summarize tempTot2 if `1'==1 local sMean2 = _result(3) quietly summarize tempTot2 if `1'==0 local uMean2 = _result(3) quietly summarize tempTot2 if `1'!=. local totSD2 = sqrt(_result(4)) local r`i'= ((`sMean2'-`uMean2')/`totSD2')*sqrt(`v`i'') local tpbcorr = `tpbcorr'+`r`i'' local theSum = `theSum' + `v`i'' /* Sum of item variances */ capture drop cnt first tempTot2 local i=`i'+1 /* Increment matrix index */ macro shift } drop ismiss /* Sort output */ local perm 1 while `perm'!=0 & `sortkey'!=0 { local i 1 local perm 0 while `i'<`nitems' { local j= `i'+1 if (`sortkey'==1 & `d`i'' < `d`j'') | /* */ (`sortkey'==2 & `r`i'' < `r`j'') | /* */ (`sortkey'==3 & "`nam`i''" > "`nam`j''") { di "`nam`i'' -- `nam`j''" local dummy "`nam`i''" local nam`i' "`nam`j''" local nam`j' "`dummy'" local dummy `n`i'' local n`i' `n`j'' local n`j' `dummy' local dummy `d`i'' local d`i' `d`j'' local d`j' `dummy' local dummy `v`i'' local v`i' `v`j'' local v`j' `dummy' local dummy `r`i'' local r`i' `r`j'' local r`j' `dummy' local perm 1 } local i=`i'+1 } /* While i */ } /* While perm */ /* Final output */ parse "`varlist'", parse(" ") di _n in gr "Kuder-Richarson coefficient of reliability (KR-20)" di in gr _n "Number of items in the scale = "`nitems' di in gr "Number of complete observations = " %4.0f `n1' _n di in gr " Item Item Item-rest" di in gr " Item | Obs difficulty variance correlation" di in gr "---------+" _dup(42) "-" local i 1 while `i' <= `nitems' { di in gr _col(2) "`nam`i''" _col(10) "|" in ye /* */ _col(12) %4.0f `n`i'' /* */ _col(21) %5.4f `d`i'' /* */ _col(32) %5.4f `v`i'' /* */ _col(43) %5.4f `r`i'' local i=`i'+1 macro shift } di in gr "---------+" _dup(42) "-" di in gr " Test |" _col(21) %5.4f `tdiff'/`nitems' /* */ _col(43) %5.4f `tpbcorr'/`nitems' _n local KR20=(`nitems'/(`nitems'-1))*(1-(`theSum'/`totVar')) di "KR20 coefficient is " %5.4f `KR20' global S_3=`tdiff'/`nitems' global S_4=`tpbcorr'/`nitems' global S_5=`nitems' global S_6=`KR20' end