|
|
|
|
************************************************************************************************************
|
|
|
|
|
* Stata program : Raschfit
|
|
|
|
|
* The Raschfit and the Raschfit-fast procedures to construct sub-scales of items
|
|
|
|
|
* Release 2 : June 8, 2004
|
|
|
|
|
*
|
|
|
|
|
* Historic
|
|
|
|
|
* Version 1 (2004-05-06) [Jean-Benoit Hardouin]
|
|
|
|
|
*
|
|
|
|
|
* Jean-benoit Hardouin, Regional Health Observatory of Orl<72>ans - France
|
|
|
|
|
* jean-benoit.hardouin@neuf.fr
|
|
|
|
|
*
|
|
|
|
|
* Use the Stata programs mmsrm, raschtest and gammasym who can be download on http://anaqol.free.fr
|
|
|
|
|
* News about this program :http://anaqol.free.fr
|
|
|
|
|
*
|
|
|
|
|
* FreeIRT Project website : http://freeirt.free.fr
|
|
|
|
|
*
|
|
|
|
|
* Copyright 2004 Jean-Benoit Hardouin
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
*
|
|
|
|
|
************************************************************************************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
program define raschfit,rclass
|
|
|
|
|
version 7.0
|
|
|
|
|
syntax varlist(min=2 numeric) [,KERnel(integer 0) NBSCales(integer 1) ITEMSorder(string) nofast]
|
|
|
|
|
if "`itemsorder'"=="" {
|
|
|
|
|
local itemsorder mspinv
|
|
|
|
|
}
|
|
|
|
|
local nbitemstot : word count `varlist'
|
|
|
|
|
tokenize `varlist'
|
|
|
|
|
|
|
|
|
|
tempfile raschfitfile
|
|
|
|
|
qui save `raschfitfile',replace
|
|
|
|
|
preserve
|
|
|
|
|
|
|
|
|
|
tempname affect
|
|
|
|
|
matrix define `affect'=J(1,`nbitemstot',0)
|
|
|
|
|
matrix colnames `affect'=`varlist'
|
|
|
|
|
|
|
|
|
|
tempname rep item matbetadim1 matbetadim2
|
|
|
|
|
if `kernel'!=0 {
|
|
|
|
|
local listkernel
|
|
|
|
|
forvalues i=1/`kernel' {
|
|
|
|
|
local listkernel `listkernel' `rep'`i'
|
|
|
|
|
matrix `affect'[1,`i']=1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local dim=0
|
|
|
|
|
local nbitemsnosel=`nbitemstot'
|
|
|
|
|
local nbitemstotdim1=`nbitemstot'
|
|
|
|
|
local nbitemsnoselukernel=`nbitemstot'-`kernel'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tempvar id betadim1 betadim2
|
|
|
|
|
forvalues i=1/`nbitemstot' {
|
|
|
|
|
qui drop if ``i''==.
|
|
|
|
|
rename ``i'' `rep'`i'
|
|
|
|
|
}
|
|
|
|
|
qui gen `id'=_n
|
|
|
|
|
tempfile filescale
|
|
|
|
|
qui save `filescale',replace
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while `nbitemsnosel'>2&`dim'<`nbscales' {
|
|
|
|
|
use `filescale',replace
|
|
|
|
|
local iteration=0
|
|
|
|
|
local dim=`dim'+1
|
|
|
|
|
if `dim'>1 {
|
|
|
|
|
local kernel=0
|
|
|
|
|
local listkernel
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
di in green "SCALE: " in yellow `dim'
|
|
|
|
|
di in green "{hline 9}"
|
|
|
|
|
di
|
|
|
|
|
tempname result`dim'
|
|
|
|
|
local listitemsnosel
|
|
|
|
|
local varlist`dim'
|
|
|
|
|
tokenize `varlist'
|
|
|
|
|
forvalues i=1/`nbitemstot' {
|
|
|
|
|
if `affect'[1,`i']==0 {
|
|
|
|
|
local varlist`dim' `varlist`dim'' ``i''
|
|
|
|
|
local listitemsnosel `listitemsnosel' `rep'`i'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
local nbitemsnosel:word count `listitemsnosel'
|
|
|
|
|
if `dim'>1 {
|
|
|
|
|
local nbitemstotdim`dim':word count `listitemsnosel'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if `kernel'>=2 {
|
|
|
|
|
local fixed=`kernel'
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
local fixed=2
|
|
|
|
|
}
|
|
|
|
|
matrix define `result`dim''=J(`=`nbitemstotdim`dim''-`fixed'',`=`nbitemstotdim`dim''+7',0)
|
|
|
|
|
|
|
|
|
|
tempname order`dim' affect`dim'
|
|
|
|
|
matrix `order`dim''=J(1,`nbitemstotdim`dim'',0)
|
|
|
|
|
matrix `affect`dim''=J(1,`nbitemstotdim`dim'',0)
|
|
|
|
|
|
|
|
|
|
if "`itemsorder'"=="msp"|"`itemsorder'"=="mspinv" {
|
|
|
|
|
di in green _col(0) "The program is ordering the items"
|
|
|
|
|
qui msp `listkernel' `listitemsnosel',c(-99) notest kernel(`kernel')
|
|
|
|
|
local scale1 "`r(scale1)'"
|
|
|
|
|
local scalenum1 "`r(scalenum1)'"
|
|
|
|
|
tokenize `scalenum1'
|
|
|
|
|
local listitemsselnum
|
|
|
|
|
forvalues j=`=`nbitemstotdim`dim''+1-`fixed''/`nbitemstotdim`dim'' {
|
|
|
|
|
matrix `order`dim''[1,``j'']=1
|
|
|
|
|
local k:word `j' of `scalenum1'
|
|
|
|
|
matrix `affect`dim''[1,`k']=1
|
|
|
|
|
local listitemsselnum `listitemsselnum' `k'
|
|
|
|
|
}
|
|
|
|
|
forvalues j=1/`nbitemsnosel' {
|
|
|
|
|
matrix `order`dim''[1,`j']=`=`nbitemsnosel'+1-`j''
|
|
|
|
|
}
|
|
|
|
|
tokenize `scale1'
|
|
|
|
|
local listitemssel ``=`nbitemstotdim`dim''-1'' ``nbitemstotdim`dim'''
|
|
|
|
|
|
|
|
|
|
local listitemsnosel
|
|
|
|
|
local listitemsnoselnum
|
|
|
|
|
|
|
|
|
|
if "`itemsorder'"=="mspinv" {
|
|
|
|
|
forvalues j=1/`=`nbitemstotdim`dim''-`fixed'' {
|
|
|
|
|
local listitemsnosel `listitemsnosel' ``j''
|
|
|
|
|
local k:word `j' of `scalenum1'
|
|
|
|
|
local listitemsnoselnum `listitemsnoselnum' `k'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if "`itemsorder'"=="msp"{
|
|
|
|
|
forvalues j=`=`nbitemstotdim`dim''-`fixed''(-1)1 {
|
|
|
|
|
local listitemsnosel `listitemsnosel' ``j''
|
|
|
|
|
local k:word `j' of `scalenum1'
|
|
|
|
|
local listitemsnoselnum `listitemsnoselnum' `k'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if "`itemsorder'"=="order" {
|
|
|
|
|
tokenize `listkernel' `varlist`dim''
|
|
|
|
|
local listitemssel
|
|
|
|
|
local listitemsselnum
|
|
|
|
|
local listitemsnosel
|
|
|
|
|
local listitemsnoselnum
|
|
|
|
|
forvalues j=1/`fixed'{
|
|
|
|
|
local listitemssel `listitemssel' `rep'`j'
|
|
|
|
|
local listitemsselnum `listitemsselnum' `j'
|
|
|
|
|
matrix `affect`dim''[1,`j']=1
|
|
|
|
|
}
|
|
|
|
|
forvalues j=`=`fixed'+1'/`nbitemstotdim`dim'' {
|
|
|
|
|
local listitemsnosel `listitemsnosel' `rep'`j'
|
|
|
|
|
local listitemsnoselnum `listitemsnoselnum' `j'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if `dim'>1 {
|
|
|
|
|
tokenize `varlist`dim''
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tokenize `varlist'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local nbitemsnosel:word count `listitemsnosel'
|
|
|
|
|
local list
|
|
|
|
|
*tokenize `varlist'
|
|
|
|
|
forvalues i=1/`=`nbitemsnosel'+`fixed'' {
|
|
|
|
|
local tmp:word `i' of "`listitemsnosel' `listitemssel'"
|
|
|
|
|
local list `list' ``i''
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
matrix colnames `result`dim''=`list' iteration nbitems ll1 AIC1 ll2 AIC2 choose
|
|
|
|
|
|
|
|
|
|
di _col(0) in green "The kernel of the scale is " in yellow _continue
|
|
|
|
|
forvalues i=1/`fixed' {
|
|
|
|
|
local inum:word `i' of `listitemsselnum'
|
|
|
|
|
di in yellow "``inum'' " _continue
|
|
|
|
|
}
|
|
|
|
|
di
|
|
|
|
|
tokenize `listitemsnosel'
|
|
|
|
|
forvalues i=1/`=`nbitemsnosel-2'' {
|
|
|
|
|
local iteration=`iteration'+1
|
|
|
|
|
di
|
|
|
|
|
di in green _col(10) "iteration:" in yellow" `iteration'"
|
|
|
|
|
di in green _col(10) "{hline 13}"
|
|
|
|
|
di
|
|
|
|
|
qui use `filescale' , clear
|
|
|
|
|
local i2:word `i' of `listitemsnosel'
|
|
|
|
|
local i2num:word `i' of `listitemsnoselnum'
|
|
|
|
|
qui keep `id' `listitemssel' `i2'
|
|
|
|
|
tempname score1 score2
|
|
|
|
|
qui gen `score2'=0
|
|
|
|
|
tokenize `listitemssel'
|
|
|
|
|
local nbitemssel: word count `listitemssel'
|
|
|
|
|
forvalues j=1/`i' {
|
|
|
|
|
local j2num:word `j' of `listitemsnoselnum'
|
|
|
|
|
if `affect`dim''[1,`j2num']==1 {
|
|
|
|
|
matrix `result`dim''[`iteration',`j']=1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
forvalues j=1/`nbitemssel' {
|
|
|
|
|
local j2:word `j' of `listitemssel'
|
|
|
|
|
local j2num:word `j' of `listitemsselnum'
|
|
|
|
|
qui replace `score2'=`score2'+`j2'
|
|
|
|
|
}
|
|
|
|
|
tokenize `listitemsnosel'
|
|
|
|
|
qui gen `score1'=`score2'+`i2'
|
|
|
|
|
forvalues j=`=`nbitemsnosel'+1'/`=`nbitemsnosel'+`nbitemssel'' {
|
|
|
|
|
matrix `result`dim''[`iteration',`j']=1
|
|
|
|
|
}
|
|
|
|
|
matrix `result`dim''[`iteration',`=`nbitemstotdim`dim''+1']=`iteration'
|
|
|
|
|
matrix `result`dim''[`iteration',`=`nbitemstotdim`dim''+2']=`nbitemssel'
|
|
|
|
|
matrix `result`dim''[`iteration',`i']=2
|
|
|
|
|
|
|
|
|
|
if "`fast'"=="" {
|
|
|
|
|
qui count if `score1'!=`=`nbitemssel'+1'&`score1'!=0&`score2'!=`nbitemssel'
|
|
|
|
|
local N=r(N)
|
|
|
|
|
di in green _col(10)"The program is estimating the parameters of the models (N=" in yellow "`N'" in green ")"
|
|
|
|
|
qui raschtest `listitemssel' `i2' if `score1'!=3&`score1'!=0&`score2'!=2, mml notest
|
|
|
|
|
|
|
|
|
|
matrix `matbetadim1'=e(beta),0
|
|
|
|
|
qui raschtest `listitemssel' if `score1'!=3&`score1'!=0&`score2'!=2, mml notest
|
|
|
|
|
matrix `matbetadim2'=e(beta),0
|
|
|
|
|
qui reshape long `rep' , i(`id') j(`item')
|
|
|
|
|
qui gen `betadim1'=0
|
|
|
|
|
qui gen `betadim2'=0
|
|
|
|
|
|
|
|
|
|
forvalues j=1/`nbitemssel' {
|
|
|
|
|
local j2num:word `j' of `listitemsselnum'
|
|
|
|
|
qui replace `betadim1'=-`matbetadim1'[1,`j'] if `item'==`j2num'
|
|
|
|
|
qui replace `betadim2'=-`matbetadim2'[1,`j'] if `item'==`j2num'
|
|
|
|
|
}
|
|
|
|
|
qui replace `betadim1'= -`matbetadim1'[1,`=`nbitemssel'+1'] if `item'==`i2num'
|
|
|
|
|
qui count if `rep'==1&`item'==`i2num'&`score1'!=`=`nbitemssel'+1'&`score1'!=0&`score2'!=`nbitemssel'
|
|
|
|
|
local nb1=r(N)
|
|
|
|
|
qui count if `item'==`i2num'&`score1'!=`=`nbitemssel'+1'&`score1'!=0&`score2'!=`nbitemssel'
|
|
|
|
|
local nb2=r(N)
|
|
|
|
|
|
|
|
|
|
qui replace `betadim2'= log(`nb1'/(`nb2'-`nb1')) if `item'==`i2num'
|
|
|
|
|
qui xi:logit `rep' i.`score1' if `score1'!=`=`nbitemssel'+1'&`score1'!=0&`score2'!=`nbitemssel', nocons offset(`betadim1') iter(100)
|
|
|
|
|
local N1=e(N)
|
|
|
|
|
matrix `result`dim''[`iteration',`=`nbitemstotdim`dim''+3']=e(ll)
|
|
|
|
|
matrix `result`dim''[`iteration',`=`nbitemstotdim`dim''+4']=2*(-e(ll)+2*(`nbitemssel'+1)-1)
|
|
|
|
|
|
|
|
|
|
tempvar newscore2
|
|
|
|
|
qui gen `newscore2'=`score2'
|
|
|
|
|
qui replace `newscore2'=99 if `item'==`i2num'
|
|
|
|
|
qui xi:logit `rep' i.`newscore2' if `score1'!=`=`nbitemssel'+1'&`score1'!=0&`score2'!=`nbitemssel', offset(`betadim2') iter(100)
|
|
|
|
|
local N2=e(N)
|
|
|
|
|
local ll=e(ll)
|
|
|
|
|
matrix `result`dim''[`iteration',`=`nbitemstotdim`dim''+5']=e(ll)
|
|
|
|
|
matrix `result`dim''[`iteration',`=`nbitemstotdim`dim''+6']=2*(-e(ll)+2*(`nbitemssel'+1)-2)
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
qui count
|
|
|
|
|
local N=r(N)
|
|
|
|
|
di in green _col(10)"The program is estimating the parameters of the models (N=" in yellow "`N'" in green ")"
|
|
|
|
|
qui raschtest `listitemssel' `i2' , mml notest
|
|
|
|
|
matrix `result`dim''[`iteration',`=`nbitemstotdim`dim''+3']=e(ll)
|
|
|
|
|
matrix `result`dim''[`iteration',`=`nbitemstotdim`dim''+4']=2*(-e(ll)+`nbitemssel'+2)
|
|
|
|
|
|
|
|
|
|
local nb1:word count `listitemssel'
|
|
|
|
|
qui mmsrm `listitemssel' `i2' , part(`nb1' 1)
|
|
|
|
|
matrix `result`dim''[`iteration',`=`nbitemstotdim`dim''+5']=e(ll)
|
|
|
|
|
matrix `result`dim''[`iteration',`=`nbitemstotdim`dim''+6']=2*(-e(ll)+`nbitemssel'+4)
|
|
|
|
|
}
|
|
|
|
|
di in green _col(10)"Unidimensional model: " _col(32) "ll: " in yellow _col(37) %12.4f `result`dim''[`iteration',`=`nbitemstotdim`dim''+3'] _col(52) in green "AIC: " in yellow _col(57) %12.4f `result`dim''[`iteration',`=`nbitemstotdim`dim''+4']
|
|
|
|
|
di in green _col(10)"Bidimensional model: " _col(32) "ll: " in yellow _col(37) %12.4f `result`dim''[`iteration',`=`nbitemstotdim`dim''+5'] _col(52) in green "AIC: " in yellow _col(57) %12.4f `result`dim''[`iteration',`=`nbitemstotdim`dim''+6']
|
|
|
|
|
tokenize `listkernel' `varlist`dim''
|
|
|
|
|
if `result`dim''[`iteration',`=`nbitemstot'+4']<=`result`dim''[`iteration',`=`nbitemstot'+6'] {
|
|
|
|
|
matrix `result`dim''[`iteration',`i']=1
|
|
|
|
|
matrix `result`dim''[`iteration',`=`nbitemstotdim`dim''+7']=1
|
|
|
|
|
local nbitemssel=`nbitemssel'+1
|
|
|
|
|
local nbitemsnosel=`nbitemsnosel'-1
|
|
|
|
|
local listitemssel `listitemssel' `rep'`i2num'
|
|
|
|
|
local listitemsselnum `listitemsselnum' `i2num'
|
|
|
|
|
matrix `affect`dim''[1,`i2num']=1
|
|
|
|
|
di _col(10) in green "The item " in yellow "``i2num''" in green " is selected in the scale " in yellow `dim'
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
matrix `result`dim''[`iteration',`=`nbitemstotdim`dim''+7']=2
|
|
|
|
|
di _col(10) in green "The item "in yellow "``i2num''" in green " is not selected in the scale " in yellow `dim'
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return matrix result`dim' `result`dim''
|
|
|
|
|
local j=`kernel'+1
|
|
|
|
|
forvalues i=`=`kernel'+1'/`nbitemstot' {
|
|
|
|
|
if `affect'[1,`i']==0 {
|
|
|
|
|
if `affect`dim''[1,`j']==1 {
|
|
|
|
|
matrix `affect'[1,`i']=`dim'
|
|
|
|
|
}
|
|
|
|
|
local j=`j'+1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
use `raschfitfile',clear
|
|
|
|
|
|
|
|
|
|
return matrix affect `affect'
|
|
|
|
|
|
|
|
|
|
end
|