The IML program is simply appended to your SAS program that reads the data. Here is an example SAS program for a 19-item questionnaire called the Morningness-Eveningness Questionairre. Most of the 540 cases have been omitted for brevity.
Title "Morningness-Eveningness Questionnaire";
Data MEQDATA;
Input id meq1 - meq19;
Cards;
1 2 3 2 2 3 3
3 2 3 3 6 3 2 4 3
2 3 3 4
2 5 3 2 3 3 1
2 1 3 4 6 3 1 3 4
4 5 3 6
3 3 2 1 1 2 3
1 2 2 3 4 0 1 2 1
2 3 2 0
4 5 3 2 3 3 1
3 2 4 4 4 2 1 4 4
1 5 3 4
5 3 2 3 3 4 4
4 1 1 3 4 5 3 4 3
1 3 3 4
6 2 2 1 2 2 3
2 1 3 2 4 0 1 2 3
2 3 2 0
....
539 4 3 3 2 2 3
2 3 2 3 4 3 1 4 3
2 3 3 2
540 1 1 1 2 2 2
1 2 1 1 4 2 3 2 2
1 3 2 0
;
The IML program is now appended:
/* *****************************************************************
*/
/*
*/
/*
REFINED ("EXACT") FACTOR SCORE EVALUATION
*/
/*
Maximize R-Square (Equation 5)
*/
/* ----------------------------------------------
*/
/* The user makes only two changes to the program (marked
in the */
/* code with numbers) before running:
*/
/* 1. The name of the data set to be analyzed
is specified on */
/* the SET subcommand. The
variables to be factored (only) */
/* are listed on the "KEEP"
subcommand.
*/
/* 2. Desired options are set on the PROC FACTOR
command. */
/*
*/
/* Note: The item correlation matrix must have an inverse
for */
/* this program to run
without producing an error.
*/
/*
*/
/* *****************************************************************
*/
options linesize=132 font='Sasfont' 8 nocenter;
data work;
set MEQDATA;
/* 1 */
keep meq1 - meq19;
Notice that only two changes to the IML program are required.
The first change is made to the "data" statement above. Specifically, the "set" command is changed to include the name of the data set I am working on, "set MEQDATA". Also, the names of the variables that I am actually factor analyzing are included on the "keep" command. Notice that the "id" (subject number) has been excluded as it is not included in the factor analysis.
proc factor data=work m=ml n=3 r=p power=4 scree outstat=fact; /* 2 */
The second change is made to the "proc factor" command. I am here requesting a maximum likelihood factor analysis (m=ml), the extraction of three factors (n=3), and promax rotation (r=p). I have set the power for the rotation to 4, a value recommended in the literature (power=4). Other options can be set, such as principal axis factoring (m=prinit) and varimax rotation (r=v). The "outstat=fact" option should NOT, however, be changed.
No other changes are required to the IML program.
Simply run the complete SAS code and examine the end of the output for
the unique information generated by the IML program.
proc standard data=work mean=0 std=1 replace out=zscores;
data ItmLabel;
set fact;
if _type_ = 'SCORE';
proc transpose data=ItmLabel out=ItmLabel;
proc iml;
reset fw=8 spaces=4;
start corr (x, corr);
nr=nrow(x);
sum=x[+,];
xpx=t(x)*x-t(sum)*sum/nr;
s=diag(1/sqrt(vecdiag(xpx)));
corr=s*xpx*s;
finish corr;
use ItmLabel;
read all var{_name_} into Item;
use fact;
read all into ItemCor where(_type_ = 'CORR');
read all into Pattern where(_type_ = 'PATTERN');
Pattern=T(Pattern);
nr=nrow(Pattern);
nc=ncol(Pattern);
read all into FactCor where(_type_ = 'FCORR');
if type(FactCor) = 'U' then
FactCor = I(nc);
FactCor=FactCor[1:nc,1:nc];
Struct=Pattern*FactCor;
use zscores;
read all into ZScore;
factor=T(DO(1,nc,1));
print , , "**** BEGIN OUTPUT FROM PROC IML **** ", , ;
FSCoef=inv(ItemCor)*Struct;
print "Factor Score Ceofficients for Items / Factors", Item FSCoef
[format=6.3], , ,;
MultR=t(Struct)*inv(ItemCor)*Struct;
RSQR=vecdiag(MultR);
MultR=sqrt(vecdiag(MultR));
MinCor=j(nrow(MultR),1,0);
do i=1 to nrow(MultR);
MinCor[i] = 2 * MultR[i]**2 - 1;
end;
print "Indeterminacy / Determinacy Indices", "(Multiple R, R-Squared,
and Minimum Correlation)"
,factor MultR [format=6.3] RSQR
[format=6.3] MinCor [format=6.3], , ,;
C=t(FSCoef)*ItemCor*FSCoef;
C=diag(C);
C=sqrt(C);
Univ=t(Struct)*FSCoef*inv(C);
Valid=vecdiag(Univ);
print "Validity Coefficients",
factor Valid [format=6.3] " compare
to MULTR --> " MultR [format=6.3], , ,;
do i=1 to nrow(Univ);
Univ[i,i] = .;
FactCor[i,i] = .;
end;
print "Univocality",
"(Rows = Factor Scores / Columns
= Factors)",
Univ [format=6.3] " compare to FACTCOR
--> " FactCor [format=6.3], , ,;
FactScor=ZScore*FSCoef;
run corr(FactScor,ScoreCor);
do i=1 to nrow(ScoreCor);
do j=1 to ncol(ScoreCor);
if i < j then do;
ScoreCor[i,j] = .;
FactCor[i,j] = .;
end;
FactCor[i,i] = 1;
end;
end;
print "Correlational Accuracy",
ScoreCor [format=6.3] " compare
to FACTCOR --> " FactCor [format=6.3], , ,;
stop;
run;