/************************************************************************************/ /* */ /* Program: Automated IV Selection */ /* By: Daniel Bauer and Kenneth Bollen */ /* Last Revised: 09/04/2003 */ /* */ /************************************************************************************/ options nocenter; title 'Automated IV Selection'; PROC IML; /************************************************************************************/ /* MODULE: FINAL_IV */ /* */ /* Create IV = Matrix with one row for every equation in the model. Column */ /* position 1 contains the dependent variable index. Remaining */ /* columns contain indices of variables that are eligible */ /* instruments for that equation. */ /* */ /************************************************************************************/ START FINAL_IV; * MAKE FINAL SELECTION OF INSTRUMENTAL VARIABLES FOR EACH EQUATION; * Check to see if potential instruments are affected by any disturbances correlating with any disturbance in the composite disturbance of equation; IV = PIV; DO i = 1 to NROW(PIV); DO p = 2 to NCOL(PIV); IF PIV[i,p] > 0 THEN DO j = 2 to NCOL(Comp); DO q = 2 to NCOL(Total); IF (Comp[i,j] > 0) & (Total[PIV[i,p],q] > 0) THEN DO; *check if element from composite and element from total in same matrix; *if so, check if covariance between disturbances = 0; IF ANY(ThetaE=Comp[i,j]) & ANY(ThetaE=Total[PIV[i,p],q]) THEN DO; DO r = 1 to NROW(ThetaE); DO c = 1 to NCOL(ThetaE); IF Comp[i,j] = ThetaE[r,c] THEN loc1 = r; IF Total[PIV[i,p],q] = ThetaE[r,c] THEN loc2 = c; END; END; IF ThetaE[loc1,loc2] > 0 THEN DO; IV[i,p] = 0; END; END; IF ANY(ThetaD=Comp[i,j]) & ANY(ThetaD=Total[PIV[i,p],q]) THEN DO; DO r = 1 to NROW(ThetaD); DO c = 1 to NCOL(ThetaD); IF Comp[i,j] = ThetaD[r,c] THEN loc1 = r; IF Total[PIV[i,p],q] = ThetaD[r,c] THEN loc2 = c; END; END; IF ThetaD[loc1,loc2] > 0 THEN IV[i,p] = 0; END; IF ANY(Psi=Comp[i,j]) & ANY(Psi=Total[PIV[i,p],q]) THEN DO; DO r = 1 to NROW(Psi); DO c = 1 to NCOL(Psi); IF Comp[i,j] = Psi[r,c] THEN loc1 = r; IF Total[PIV[i,p],q] = Psi[r,c] THEN loc2 = c; END; END; IF Psi[loc1,loc2] > 0 THEN IV[i,p] = 0; END; END; END; END; END; END; PRINT IV; * Print IV matrix; PRINT '****** MODEL-IMPLIED INSTRUMENTAL VARIABLES ******'; PRINT 'DV = Dependent Variable; IVs = Instrumental Variables'; PRINT '(Numbers Correspond to User-Defined Indices for Variables)'; IV2 = IV; *Sorting by DV index; IV[rank(IV[,1]),]=IV2; DO i = 1 to NROW(IV); DV = IV[i,1]; IVs = {0}; DO j = 2 to NCOL(IV); IF IV[i,j] > 0 THEN IVs = IVs||IV[i,j]; END; IF NCOL(IVs) > 1 THEN IVs = IVs[1,2:NCOL(IVs)]; PRINT DV IVs; END; FINISH; /************************************************************************************/ /* MODULE: POTENTIAL_IV */ /* */ /* Create PIV = Matrix of potential instrumental variables. Column position 1 */ /* contains the variable index of the dependent variable from the */ /* equation. The remaining column positions contain the indices */ /* of variables that are not affected by disturbances in composite */ /* disturbance of the equation. */ /* */ /************************************************************************************/ START POTENTIAL_IV; * CREATE MATRIX PIV OF POTENTIAL INSTRUMENTAL VARIABLES FOR EACH EQUATION; DO i = 1 to NROW(COMP); PIVi = COMP[i,1]; DO p = 1 to NROW(Total); inst = 1; DO j = 2 to NCOL(COMP); IF (COMP[i,j] > 0) & (Inst = 1) THEN DO q = 2 to NCOL(Total); IF COMP[i,j] = TOTAL[p,q] THEN Inst = 0; END; END; IF inst = 1 THEN PIVi = PIVi||TOTAL[p,1]; END; *array PIVi into matrix PIV accounting for fact that they vary in length; IF i = 1 THEN PIV = PIVi; ELSE DO; IF NCOL(PIV) = NCOL(PIVi) THEN; ELSE DO; IF NCOL(PIV) > NCOL(PIVi) THEN DO; *Pad PIVi with zeros to be conformable; Add = J(1,(NCOL(PIV)-NCOL(PIVi)),0); PIVi = PIVi||Add; END; ELSE DO; *Pad PIV with zeros to be conformable; Add = J(NROW(PIV),(NCOL(PIVi)-NCOL(PIV)),0); PIV = PIV||Add; END; END; PIV = PIV//PIVi; END; END; PRINT PIV; FINISH; /************************************************************************************/ /* MODULE: EFFECTS */ /* */ /* Create TOTAL = Matrix with one row for every variable in the model. Column */ /* position 1 contains the variable index. Remaining columns */ /* contain indices of disturbances that have a non-zero total */ /* effect on that variable. */ /* */ /************************************************************************************/ START EFFECTS; /***** calculate total effects of disturbances on observed variables *****/ * FIRST CALCULATE TOTAL EFFECTS OF ERRORS ON Ys; IF y1 > 0 THEN DO; *calculate total effects of epsilon on ys; TotalE = VECDIAG(ThetaE); *calculate total effects of zeta on y1 through Beta; TotalZ_y1 = INV(I(NCOL(y1))-Beta); *calculate total effects of zeta on y2 through Lambda; IF y2 > 0 THEN DO; TotalZ_y2 = ly2*TotalZ_y1; END; * Replacing non-zero elements in TotalZ_y1 and TotalZ_y2 with appropriate zeta; DO i = 1 to NROW(TotalZ_y1); DO j = 1 to NCOL(TotalZ_y1); IF TotalZ_y1[i,j] ^= 0 THEN TotalZ_y1[i,j] = Psi[j,j]; END; END; IF y2 > 0 THEN DO i = 1 to NROW(TotalZ_y2); DO j = 1 to NCOL(TotalZ_y2); IF TotalZ_y2[i,j] ^= 0 THEN TotalZ_y2[i,j] = Psi[j,j]; END; END; *Combine TotalZ_y1 and TotalZ_y2 and sort by index to match up with TotalE; TotalZ_y1 = (y1`)||TotalZ_y1; *Indexing TotalZ_y1; IF y2 > 0 THEN DO; TotalZ_y2 = (y2`)||TotalZ_y2; *Indexing TotalZ_y2; TotalY = TotalZ_y1//TotalZ_y2; END; ELSE DO; TotalY = TotalZ_y1; END; TotalY2 = TotalY; TotalY[rank(TotalY[,1]),]=TotalY2; TotalY = TotalY||TotalE; IF x1 = 0 THEN DO; Total = TotalY; END; END; * CALCULATE TOTAL EFFECTS OF ERRORS ON Xs; IF x1 > 0 THEN DO; IF x2 > 0 THEN TotalX = (x1`)//(x2`); *Creating Index Column of TotalX; ELSE TotalX = x1`; TotalD = VECDIAG(ThetaD); TotalX2 = TotalX; *Sorting Index Column; TotalX[rank(TotalX[,1]),]=TotalX2; TotalX = TotalX||TotalD; *Adding total effects of delta; IF y1 = 0 THEN DO; Total = TotalX; END; END; * COMBINE TOTALX AND TOTALY INTO ONE MATRIX; * Need to pad TotalX or TotalY with 0s so equivalent # columns in each; IF y1 > 0 & x1 > 0 THEN DO; IF NCOL(TotalY) > NCOL(TotalX) THEN DO; Add = J(NROW(TotalX),(NCOL(TotalY)-NCOL(TotalX)),0); TotalX = TotalX||Add; END; ELSE DO; Add = J(NROW(TotalY),(NCOL(TotalX)-NCOL(TotalY)),0); TotalY = TotalY||Add; END; Total = TotalY//TotalX; END; * Sort Total; Total2 = Total; Total[rank(Total[,1]),]=Total2; PRINT TOTAL; FINISH; /************************************************************************************/ /* MODULE: COMPOSITE */ /* */ /* Create COMP = Matrix with one row for every equation in the model. Column */ /* position 1 contains the dependent variable index. Remaining */ /* columns contain indices of disturbances that have a non-zero */ /* total effect on that variable. */ /* */ /************************************************************************************/ START COMPOSITE; * First need to keep track of position of each variable index in y or x series; * Sorting Y and X vectors into index order; IF y1 > 0 THEN DO; VecY = y1`; IF y2 > 0 THEN VecY = VecY//y2`; OrderY = VecY; OrderY[rank(OrderY),]=VecY; OrderY = Rank(OrderY)||OrderY; END; IF x1 > 0 THEN DO; VecX = x1`; IF x2 > 0 THEN VecX = VecX//x2`; OrderX = VecX; OrderX[rank(OrderX),]=VecX; OrderX = Rank(OrderX)||OrderX; END; * Find Composite Disturbance for each equation; DO i = 1 to NROW(PRED); *for each DV, pull predictors from PRED; COMPi = PRED[i,1]; *set first column in row of DIST to dv index; IF y1 > 0 THEN DO j = 1 to NCOL(y1); *if DV is in y1, add corresponding zeta; IF COMPi = y1[j] THEN DO; COMPi = COMPi||Psi[j,j]; END; END; DO j = 1 to NCOL(PRED); *examine each variable in equation (including dv); IF y1 > 0 THEN DO k = 1 to NROW(OrderY); *identify source of variable and find its error; IF PRED[i,j] = OrderY[k,2] THEN COMPi = COMPi||ThetaE[OrderY[k,1],OrderY[k,1]]; END; IF x1 > 0 THEN DO k = 1 to NROW(OrderX); IF PRED[i,j] = OrderX[k,2] THEN COMPi = COMPi||ThetaD[OrderX[k,1],OrderX[k,1]]; END; END; *array COMPi into matrix COMP accounting for fact that they vary in length; IF i = 1 THEN COMP = COMPi; ELSE DO; IF NCOL(COMP) = NCOL(COMPi) THEN; ELSE DO; IF NCOL(COMP) > NCOL(COMPi) THEN DO; *Pad COMPi with zeros to be conformable; Add = J(1,(NCOL(COMP)-NCOL(COMPi)),0); COMPi = COMPi||Add; END; ELSE DO; *Pad COMP with zeros to be conformable; Add = J(NROW(COMP),(NCOL(COMPi)-NCOL(COMP)),0); COMP = COMP||Add; END; END; COMP = COMP//COMPi; END; END; PRINT COMP; FINISH; /************************************************************************************/ /* MODULE: PREDICTORS */ /* */ /* Create PRED = Matrix with one row for every equation in the model. Column */ /* position 1 contains the dependent variable index. Remaining */ /* columns contain varaible indices of the predictors in the */ /* equation. */ /* */ /************************************************************************************/ START PREDICTORS; *Constructing PRED matrix of predictors for which IVs are needed; *Create PREDi for each variable in y1 (y1_i); *Search Beta and Gamma matrix for y1s and x1s that influence y1_i; IF y1 > 0 THEN DO i = 1 to NROW(Beta); PREDi = y1[i]; *Starting with DV index; DO j = 1 to NCOL(Beta); IF Beta[i,j] ^= 0 THEN DO; PREDi = PREDi||y1[j]; END; END; IF x1 > 0 THEN DO j = 1 to NCOL(Gamma); IF Gamma[i,j] ^= 0 THEN DO; PREDi = PREDi||x1[j]; END; END; *Add PREDi to larger PRED matrix here; IF i=1 THEN DO; PRED = PREDi; END; ELSE DO; *array PREDi into matrix PRED accounting for fact that they vary in length; IF NCOL(PRED) ^= NCOL(PREDi) THEN DO; IF NCOL(PRED) > NCOL(PREDi) THEN DO; *Pad PREDi with zeros to be conformable; Add = J(1,(NCOL(PRED)-NCOL(PREDi)),0); PREDi = PREDi||Add; END; ELSE DO; *Pad PRED with zeros to be conformable; Add = J(NROW(PRED),(NCOL(PREDi)-NCOL(PRED)),0); PRED = PRED||Add; END; END; PRED = PRED//PREDi; END; END; *Create PREDi for y2, concatenate with PRED; IF y2 > 0 THEN DO i = 1 to NCOL(y2); PREDi = y2[i]; *Starting with DV index; DO j = 1 to NCOL(y1); IF ly2[i,j] > 0 THEN DO; PREDi = PREDi||y1[,j]; END; END; *array PREDi into matrix PRED accounting for fact that they vary in length; IF NCOL(PRED) = NCOL(PREDi) THEN; ELSE DO; IF NCOL(PRED) > NCOL(PREDi) THEN DO; *Pad PREDi with zeros to be conformable; Add = J(1,(NCOL(PRED)-NCOL(PREDi)),0); PREDi = PREDi||Add; END; ELSE DO; *Pad PRED with zeros to be conformable; Add = J(NROW(PRED),(NCOL(PREDi)-NCOL(PRED)),0); PRED = PRED||Add; END; END; PRED = PRED//PREDi; END; *Create PREDi for x2, concatenate with PRED; IF x2 > 0 THEN DO i = 1 to NCOL(x2); PREDi = x2[i]; *Starting with DV index; DO j = 1 to NCOL(x1); IF lx2[i,j] > 0 THEN DO; PREDi = PREDi||x1[,j]; END; END; IF (y1 = 0) & (i=1) THEN DO; PRED = PREDi; END; ELSE DO; *array PREDi into matrix PRED accounting for fact that they vary in length; IF NCOL(PRED) = NCOL(PREDi) THEN; ELSE DO; IF NCOL(PRED) > NCOL(PREDi) THEN DO; *Pad PREDi with zeros to be conformable; Add = J(1,(NCOL(PRED)-NCOL(PREDi)),0); PREDi = PREDi||Add; END; ELSE DO; *Pad PRED with zeros to be conformable; Add = J(NROW(PRED),(NCOL(PREDi)-NCOL(PRED)),0); PRED = PRED||Add; END; END; PRED = PRED//PREDi; END; END; PRINT PRED; FINISH; /************************************************************************************/ /* MODULE: MAIN */ /* */ /* User assigns index numbers to variables and disturbances and defines the model */ /* */ /************************************************************************************/ START MAIN; /* INDEX VARIABLES IN THE MODEL */ /* Create row vectors designating index of scaling and nonscaling variables. */ /* Numbers will subsequently be used to reference variables. Use {0} if no */ /* variables are in the vector. */ /* Note that the order is arbitrary (ys do not have to precede xs etc), but */ /* the specified order must be followed in other matrices. For example, */ /* ThetaE(1,1)references the error variance of whichever y has the first */ /* position (lowest number) in the variable list for y1 and y2. */ y1 = {1 5}; * scaling y's; y2 = {2 3 4 6 7 8}; * non-scaling y's; x1 = {9}; * scaling x's (and exogenous x's); x2 = {10 11}; * non-scaling x's; /* SET UP PARAMETER MATRICES */ /* Parameter matrices should be specified in binary -- non-zero elements */ /* labeled 1; zero elements labeled 0. Set null matrices to {0}. */ /* Create loading matrix for y2 and x2 variables = lambda y2 and lambda x2 */ ly2 = {1 0, 1 0, 1 0, 0 1, 0 1, 0 1}; lx2 = {1, 1}; /* Create matrices of structural parameters Beta and Gamma */ /* Note - may be necessary to use values other than 1 to code non-zero effects */ /* in Beta if you get an error that 'Matrix should be non-singular' */ Beta = {0 0, 1 0}; Gamma = {1, 1}; /* INDEX DISTURBANCES */ /* Each unique non-zero element in ThetaE, ThetaD and Psi should be given a */ /* unique index number. It is helpful to label the diagonals of ThetaE and */ /* ThetaD with the same numers that index the Y and X variables that the elements */ /* correspond to for easy reference later. If there are no parameters in a */ /* matrix, set it to {0}. Note that upper and lower off-diagonal matrices should */ /* contain the same numbers. */ ThetaE = { 1 0 0 0 12 0 0 0, 0 2 0 16 0 13 0 0, 0 0 3 0 0 0 14 0, 0 16 0 4 0 0 0 15, 12 0 0 0 5 0 0 0, 0 13 0 0 0 6 0 17, 0 0 14 0 0 0 7 0, 0 0 0 15 0 17 0 8}; ThetaD = { 9 0 0, 0 10 0, 0 0 11}; Psi = {18 0, 0 19}; RUN PREDICTORS; RUN COMPOSITE; RUN EFFECTS; RUN POTENTIAL_IV; RUN FINAL_IV; FINISH; RUN; QUIT;