Running Winsteps® for Rasch Model Analysis from within SAS ® [1]
(Also in Appendix, Running HLM® program from within SAS®)
Kazuaki (Kaz) Uekawa, Ph.D.
Visiting Scholar at Department of Sociology, the University of Chicago
Independent SAS consultant
kuekawa@alumni.uchicago.edu
www.src.uchicago.edu/users/ueka
© Kazuaki Uekawa 2002 All Rights Reserved
Summary
Winsteps is a Rasch Model Analysis Software written by John M. Linacre (www.winsteps.com). It is a user-friendly program, but like other stand-alone programs, it requires many files. Before I “invented” the method that I introduce here, I needed to remember names and locations of so many files, including the files that prepared the data, the different versions of control files, different versions of result outputs, and different versions of batch mode execution files. When I was going insane, I came up with this idea of gathering all the necessary programming in one central location, i.e., a SAS program file.
In Appendix, I also attached my experimental SAS program that runs Bryk, Raudenbush, & Congdon’s HLM® program. It uses a sample data that accompanies the HLM software, so it is ready to run.
Also from www.src.uchicago.edu/users/ueka
a) Some preparation
work, such as assigning library name and creating some macro statements.
c) Use the SAS data set just
read and write out a WINSTEP®-ready simple-text data set.
d) Write out a WINSTEP®-ready
control file from within SAS.
e) Run WINSTEPS from within
SAS and let it read a control file using X-statement.
f) Read in item measure files
(*.if) and create SAS data set.
g) Do analysis of your choice
using the data just created above.
h) Read in person measure file
(*pf) and create a SAS data set.
i) Using the
SAS data set just created, do analyses of your choice.
/*type
the location where winstep is installed*/
%let win= C:\WINSTEPS\winsteps;
/*type
the path of a working directory*/
%let direc=C:\WINSTEPS\;
libname here "&direc" ;
/*type
the name of your SAS data*/
%let dataname=winstep_sas_example;
%let WD=&direc;
%let scale=F1dev;
%let ni =22;/*n of items*/
%let codes=1234;
%let X=YYY; is the most simple
form of macro statement in SAS. It
means that X will be used as a token term for YYY. Every time SAS reads &X in the program, it will replace it
with YYY.
Libname is the statement that
should come at the beginning of all SAS programs. It gives a nickname to a working directory. For example, libname here “C:\” means,
from now on, C directory will be referred to as “here”.
data &scale;set here.&dataname;
/*women
have DIF for these items, so treat them separately*/
if sex=2 then do;
F_abuse=abuse;
abuse=.;
F_destroy=destroy;
destroy=.;
F_fight=fight;
fight=.;
F_copy=copy;
copy=.;
end;
/*instrumental
variable to create a blank (maybe I don't really need this)*/
blank=' ';
run;
The
data set used for this exercise can be found with this document at
www.src.uchicago.edu. It is read
at the beginning of this program.
Because I found that item difficulty of some items vary by gender, I am
treating these variables as separate items for female students. In this application, “If sex=2 then do”
means do the following programming only for women.
data &scale;set &scale;
file "&WD.&scale..dat";
put
(STDID)
(5.0)
(blank)(1.0)
(sex)
(1.0)
(
late cut skip cheat copy fight gang racist sexist steal destroy smoke drink
drug weapon abuse talkback disobey
F_abuse
F_destroy F_fight F_copy
)
(1.0);
run;
&scale is a macro
token. It is replaced by whatever
term was defined by let statement.
Earlier, I did %let scale=F1dev; so it will be replaced by this. F1dev is a name of a variable that I assigned.
%macro varnames;/*22 items*/
put "late";
put "cut";
put "skip";
put "cheat";
put "copy";
put "fight";
put "gang";
put "racist";
put "sexist";
put "steal";
put "destroy";
put "smoke";
put "drink";
put "drug";
put "weapon";
put "abuse";
put "talkback";
put "disobey";
put "F_abuse";
put "F_destroy";
put "F_fight";
put "F_copy";
%mend varnames;
filename new "&WD&scale..con";
data _null_;
file new;
put '&inst ';
put " item1=8";
put " name1=1";
put " ni=&ni";
put " HLINES=n";
put " ;target=y";
put ";table=";
put " person=student";
put " item=question";
put " codes=&codes";
put " udecim=6";
put "; pfile=&scale..pfile";
put "; ifile=&scale..ifile";
put " csv=n";
put " data=&WD&scale..dat";
put ' &end';
%varnames ;
put " END
NAMES";
run;
When the content inside the
parentheses contain &, use single quotes instead of double quotes, so SAS
will recognize it as a part of text rather than as a SAS-specific functional
term.
option xwait xsync;
/*This
run uses the whole sample*/
x "start &win &WD&scale..con &WD&scale._whole.out ifile=&WD&scale._whole.ifile
pfile=&WD&scale._whole.pfile ";
/*This
run uses only boys’ data. See how
I used pselect option*/
x "start &win &WD&scale..con &WD&scale._boys.out pselect=??????1* ifile=&WD&scale._boys.ifile";
/*This
run uses only girls’ data. See how
I used pselect option*/
x "start &win &WD&scale..con &WD&scale._girls.out pselect=??????2* ifile=&WD&scale._girls.ifile";
X allows SAS to control
external software by activating a DOS prompt. This is like doing a batch model run from within SAS.
Option xwait xsync is supposed
to let each X line to wait until the previous X line finishes its job. But it is not working, so I will have
to contact SAS about this (support@sas.com).
It is okay for these three
lines of runs to happen at the same time, but it may occupy too much memory.
/*creating
a blank data to which real data are appended (Maybe there is a better way than
this)*/
data blank;
set _null_; ENTRY=.; MEASURE=. ; STTS=.; COUNT=.; SCORE=.;
STDER=.; INMSQ=.; INZSTD=.; OUTMS =.; OUTZSTD=.;
DISPL =.; CORR =.; WEIGHT=.; G =.; M ="
"; NAME="
"; MFIT =.; subgroup="
";
/*item
files produced by winsteps are now read by SAS*/
%macro edward (suji);
FILENAME
raw2 "&WD&scale._&suji..ifile";
data
outdata;
infile
raw2 missover;
input
ENTRY
MEASURE STTS COUNT
SCORE STDER INMSQ INZSTD
OUTMS OUTZSTD DISPL CORR WEIGHT G M
$ NAME $;
if
stTS < = -2 then measure=.;
MFIT=0;
if
OUTMS > 2 then MFIT=1;
if
entry > -999;
subgroup="&suji";
proc
sort;
by
name;
run;
proc
append base=blank data=outdata;
run;
%mend edward;
%edward
(suji=whole);
%edward
(suji=boys);
%edward
(suji=girls);
/*now
the data is converted into a permanent data set*/
data here.&scale._idif;set blank;run;
Here I am printing the data to see the content and
am graphing to see if whether item difficulty varies by gender.
/*see
the content of item file*/
proc print data=here.&scale._idif;
title "Show the contents of
Item Files";
run;
/*graphing*/
goptions gsfname=outfiles dev=gif gunit=pct cback=white htitle=6 htext=3 ftext=swissb ctext=black vsize=8 hsize=8;
title1 font=duplex "Item
difficulty varying by subsamples";
footnote1 "";
symbol interpol=spline /*join*/ value=dot height=1;
proc gplot data=here.&scale._idif;
plot measure*subgroup=name / /*overlay*/;
run;
quit;
/*Read
in person measure file and create a SAS data*/
FILENAME raw1 "&direc.&scale._whole.pfile";
data &scale;infile raw1 missover;
*length
TchID $ 8;
input ENTRY measure STTS COUNT SCORE
STDER INMSQ INZSTD
OUTMS
OUTZSTD DISPL CORR WEIGHT
STDID
;
/*removing
observations depending on the status of observations*/
if stTS < = -2 then measure=.;
/*Creating
a flag variable that indicates if the measure had a large misfit*/
MFIT=0;
if OUTMS > 2 then MFIT=1;
if entry > -999;
/*give
unique variable names for convinience*/
&scale.R=measure;
&scale.ERR=STDER;
&scale.MFIT=MFIT;
/*I
am logging the measure here*/
&scale.RLOG=log(measure+
10);
run;
Here I am getting descriptive statistics, as well as plots (proc univariate). I am standardizing the measures (proc standard). Then I am saving them into a new SAS data set (data step) and then looking at the content (proc print).
/*checking
the distribution of the measures*/
proc univariate data=F1dev plot;
var F1devR F1devRLOG;
run;
/*making
z-scores = standardizing with a mean of 0 and standard deviation of 1*/
proc standard data=F1dev out=F1dev mean=0 std=1;
var F1devR F1devRLOG;
run;
/*creating
a permanent SAS data*/
data here.F1dev;set F1dev;
keep STDID F1devR F1devRlog;
/*Just
checking the content of it by printing it out*/
proc print data=here.F1dev;
var STDID F1devR;run;
APPENDIX
Running Bryk, Randenbush, & Congdon’s HLM from within SAS
I wrote this program a while ago. It works, but I don’t really use this because I have never succeeded in creating SSM file with my own data. This particular program uses a sample data that accompanies HLM program, so as long as you installed SAS in a default place, anyone can copy and paste this into SAS and run it. The programming here is relatively simple. The basic idea is the same as my WINSTEP-SAS program. It writes out a control file and runs it with HLM. Then it reads in the output file and applies some analyses.
options noxwait xsync;
libname here "C:\HLM5\Examples\AppendxA";
libname SAS "C:\Program
Files\SAS Institute\SAS\V8";
data hlm;
input line $ 1-75;
cards;
#This command file was run with
C:\HLM5\Examples\AppendxA\HSB.SSM
NUMIT:10000
STOPVAL:0.0000010000
NONLIN:n
LEVEL1:MATHACH=INTRCPT1+SES,1+RANDOM
LEVEL2:INTRCPT1=INTRCPT2+SECTOR+MEANSES+RANDOM/
LEVEL2:SES=INTRCPT2+SECTOR+MEANSES+RANDOM/
RESFIL:Y/
RESFILTYPE:SAS
RESFILNAME:C:\HLM5\Examples\AppendxA\HSB1.sas
HETEROL1VAR:n
PRINTVARIANCE-COVARIANCE:Y
ACCEL:5
LVR:N
LEV1OLS:10
HYPOTH:n
FIXTAU:3
CONSTRAIN:N
OUTPUT:C:\HLM5\Examples\AppendxA\hsb1.out
TITLE:INTERCEPT AND SLOPES-AS-OUTCOMES MODEL
;
data hlm2;set hlm;
file "C:\HLM5\Examples\AppendxA\program1.txt";
put (line) (100.0);
run;
x "C:\HLM5\HLM2
C:\HLM5\Examples\AppendxA\HSB.SSM C:\HLM5\Examples\AppendxA\program1.txt ";
filename stud "C:\HLM5\Examples\AppendxA\hsb1.out";
data studd ;infile stud length=lg;input @;input @1 eachline $varying78. lg;
data coeff;set studd;
where eachline contains ", G";
run;
proc print;run;
data deviance;set studd;
where eachline contains " Deviance";
proc print;run;
%include "C:\HLM5\Examples\AppendxA\HSB1.sas" ;
run;
data residual;set sas.resfil;
run;
proc print;run;
The End of Document