Annotated Example of IML Program for Creating Coarse Factor Score Estimates
based on Thurstone's Regression Approach
(annotation appears in red)

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. The output generated from this program can be used to select items to include in the computation of the coarse factor scores.
 

Title "MEQ Data set";
Data MEQDATA;
  input sub 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
  7  2  1  3  4  4  2  3  3  2  3  4  2  4  3  3  3  5  3  6
  8  3  3  2  3  4  3  3  2  4  3  6  2  1  3  4  2  5  4  4
  9  3  3  2  3  2  4  1  1  1  3  4  3  1  3  3  1  3  2  2
 10  2  2  2  3  3  1  2  2  2  3  4  2  1  2  2  1  3  3  0
......
538  3  3  3  3  4  4  3  2  3  3  4  2  2  3  4  1  3  2  1
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:

/* *************************************************************** */
/*                                                                 */
/*           CREATING COARSE ("SIMPLIFIED") FACTOR SCORES          */
/*               (Based on Eq. 5: Maximize R-squared)              */
/*          ----------------------------------------------         */
/*  The user makes only one change to the program (marked in the   */
/*  code with a number) before running:                            */
/*    1. 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;

proc factor data=meqdata m=ml n=2 r=p power=4 scree score outstat=fact;
  var meq1 - meq19;                                                  /* 1 */
 

Notice that only one change is made to the IML program. Specifically, the "proc factor" command is changed. I am here requesting a maximum likelihood factor analysis (m=ml), the extraction of two factors (n=2), 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.

data ItmLabel;
  set fact;
  if _type_ = 'SCORE';
proc transpose data=ItmLabel out=ItmLabel;

proc iml;
reset fw=8 spaces=4;

   start sort(FSCVect, item, RankCoef, ItemR);
     n=nrow(FSCVect);
     ct=j(n,1,0);
     RankCoef=j(n,1,-9999);
     ItemR=j(n,1,'       ');
     do j=1 to n;
       max=-9999;
       do i=1 to n;
         if FSCVect[i] > max then do;
           max=FSCVect[i];
           place=i;
           end;
       end;
       FSCVect[place]=-9999;
       RankCoef[j]=max;
       ItemR[j]=item[place];
       ct[j]=j;
     end;
     RankCoef=ct||RankCoef;
   finish sort;

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;
read all into N where(_type_ = 'N');

print , , "**** BEGIN OUTPUT FROM PROC IML **** ", , ;
FSCoef=inv(ItemCor)*Struct;
print "Factor Score Ceofficients for Items / Factors", Item FSCoef [format=6.3], , ,;

do j=1 to nc;
  FSCVect=FSCoef[,j];
  run sort(FSCVect, item, RankCoef, Itemr);
  ranks=RankCoef;
  RankCoef=RankCoef[,2];
  label=concat('Ranked Factor Score Coefficients: Factor ',char(j,2,0));
  print label, Itemr RankCoef [format=6.3];
  call pgraf(ranks, itemr, 'Rank','Factor Score Coefficient',label);
end;

C=t(FSCoef)*ItemCor*FSCoef;
C=diag(C);
C=sqrt(C);
Univ=t(Struct)*FSCoef*inv(C);
Valid=vecdiag(Univ);
Rinv=inv(ItemCor);
Errors=j(nr,nc,0);
do i=1 to nr;
  do j=1 to nc;
    Errors[i,j] = sqrt((Rinv[i,i] * (1 - Valid[j]**2)) / (N[j] - nr - 1));
  end;
end;
t_values=j(nr,nc,0);
do i=1 to nr;
  do j=1 to nc;
    if Errors[i,j] <> 0 then t_values[i,j] = FSCoef[i,j] / Errors[i,j];
    else t_values[i,j] = 0;
  end;
end;
print "Standard Errors and t-values for Factor Score Ceofficients", Item Errors [format=6.3] t_values [format=6.3], , ,;

multR=t(Struct)*inv(ItemCor)*Struct;
SMC=vecdiag(multR);
/* multR=sqrt(vecdiag(multR)); */
Contrib = j(nr+1,nc,0);
do i=1 to nr;
  do j=1 to nc;
    Contrib[i,j] = FSCoef[i,j] * Struct[i,j];
  end;
end;
Item = Item // '.' // 'TOTALS';
Contrib[nr+1,] = .;
Contrib = Contrib // T(SMC);
print "Total Item Contribution to Squared Multiple Correlation", Item Contrib [format=6.3];
stop;
run;