* SEQGROUPS. * This program computes a variety of basic sequential analysis statistics for more than one group/segment. The data are assumed to be a series of integer codes with values ranging from "1" to what ever value the user specifies in the "ncodes" computation at the start of the program. * Set 'seed' to a non-negative integer; 1953125 is good. SET MXLOOPS=3000000 length=none printback=none width=80 seed = 1953125. matrix. * Enter the number of possible code values here. compute ncodes = 6. * Enter labels for the codes (5 characters maximum), if desired, here. compute labels={"Code 1","Code 2","Code 3","Code 4","Code 5","Code 6", "Code 7","Code 8","Code 9","Code 10","Code 11","Code 12","Code 13", "Code 14","Code 15"}. * Enter the lag number for the analyses here. compute lag = 1. * Can adjacent events be coded the same? Enter "0" if adjacent events can NEVER be the same; Enter "1" if adjacent events can ALWAYS be the same; Enter "2" if some adjacent events can, and others cannot, be the same; then scroll down and enter the appropriate "ONEZERO" matrix for your data. compute adjacent = 1. * Enter "1" for one-tailed tests; enter "2" for two-tailed tests. compute tailed = 2. * Desired test? Enter "1" for homogeneity, enter "2" for stationarity. compute test = 1. * Desired output? Enter "1" for pooled data only, enter "2" for all data sets. compute output = 2. * Which results do you want to have saved in an outfile? Enter "1" for transitional frequencies, Enter "2" for transitional probabilities, Enter "3" for Adjusted residuals, Enter "4" for Yule's Q values Enter "5" for kappas. compute outfile = 1. * to save and view the outfile, see the SAVE command at the end of this file. * Enter/read the data into a matrix with the name "alldata", with code values > 999 indicating different groups or segments. compute alldata = { 1000; 2;5;2;4;2;5;2;4;2;4;2;2;5;2;4;2;5;3;4;3;4;1;4;4;1; 2;5;2;1;5;4;2;5;1;4;4;2;3;6;6;2;2;6;5;5;5;6;3;6;3; 3;6;3;2;5;3;5;2;6;2;2;2;5;2;4;4;5;2;5;2;5;5;4;2;5; 5;5;2;5;2;5;2;5;2;2;5;2;5;2;2;5;5;2;2;2;5;2;5;2;5; 2;5;2;2;5;2;5;3;5;2;5;5;2;2;5;2;2;5;2;6;2;5;4;2;5; 2;4;4;2;1;2; 2000; 5;2;5;2;5;5;5;3;5;2;5;5;2;5;5;2;5;2;5; 2;4;2;4;2;5;4;2;2;5;2;5;5;5;2;5;2;5;5;2;5;2;5;5;2; 1;2;5;1;5;1;5;5;4;2;2;2;3;6;3;6;3;6;3;6;3;6;3;3;6; 6;6;5;1;2;5;2;5;5;2;4;5;5;2;5;5;2;5;2;5;2;5;1;5;4; 2;2;5;2;5;2;5;4;1;4;4;2;4;4;2;4;2;3;5;4;2;2;5;2;6; 1;4;1;4;5;5;5;4;5;2;4;5; 3000; 5;2;5;2;2;2;5;2;2;5;2;2;4; 2;2;2;6;2;4;3;3;3;3;2;3;6;3;5;3;3;5;3;2;2;2;2;6;3; 6;3;6;2;6;1;6;3;3;3;3;5;3;5;2;5;3;3;6;3;1;4;1;5;1; 5;6;3;3;6;3;6;3;6;3;6;3;6;3;3;6;3;6;3;2;5;2;5;2;5; 2;5;2;2;2;3;5;1;6;1;6;6;6;1;6;6;1;6;1;6;2;5;1;6;6; 6;2;2;6;6;6;2;6;2;6;2;5;5;5;5;5;5;6 }. * pooling data for stationarity analyses. do if test = 2. compute totdata = {0}. loop #x = 1 to nrow(alldata). do if ( alldata(#x,1) < 1000 ). compute totdata = { totdata ; alldata(#x,1) }. end if. end loop. compute totdata = totdata(2:nrow(totdata),1). compute freqst = make(ncodes,ncodes,0). loop #y = 1 to nrow(totdata). do if ( #y + lag le nrow(totdata) ). compute freqst((totdata(#y,1)),(totdata((#y+lag),1))) = freqst((totdata(#y,1)),(totdata((#y+lag),1))) + 1. end if. end loop. end if. compute out = make(1,(ncodes*ncodes+1),0). compute each = make(1,(ncodes*ncodes),0). compute start = 2. compute lastone = 0. loop #a = 1 to nrow(alldata). compute freqs = make(ncodes,ncodes,0). compute data = 0. loop #b = start to nrow(alldata). do if ( alldata(#b,1) < 1000 ). compute data = { data ; alldata(#b,1) }. compute end = #b. end if. do if ( alldata(#b,1) ge 1000 ). compute start = #b + 1. break. end if. end loop. compute data = data(2:nrow(data),1). compute lastone = { lastone; data(nrow(data),1) }. compute freqs = make(ncodes,ncodes,0). loop #c = 1 to nrow(data). do if ( #c + lag le nrow(data) ). compute freqs((data(#c,1)),(data((#c+lag),1))) = freqs((data(#c,1)),(data((#c+lag),1))) + 1. end if. end loop. compute each = { each; reshape(freqs,1,(ncodes*ncodes)) }. end loop if ( end = nrow(alldata) ). compute lastone = { lastone(2:nrow(lastone),1); lastone(nrow(lastone),1) }. do if ( test = 1). compute freqst = reshape(csum(each),ncodes,ncodes). end if. compute rowtott = rsum(freqst). compute pp = make(ncodes,ncodes,0). compute each = { each(2:nrow(each),:) ; reshape(freqst,1,ncol(each)) }. * initializing. compute lrx2sh = {0}. loop #d = 1 to nrow(each). compute lrx2t = {0}. compute freqs = reshape(each(#d,:),ncodes,ncodes). compute rowtots = rsum(freqs). compute coltots = csum(freqs). compute ntrans = msum(rowtots). compute prows = rowtots / ntrans. compute pcols = coltots / ntrans. compute p = make(ncodes,ncodes,-9999). compute et = make(ncodes,ncodes,-9999). compute expfreq = make(ncodes,ncodes,-9999). compute zadjres = make(ncodes,ncodes,-9999). compute pzadjres = make(ncodes,ncodes,1). compute yulesq = make(ncodes,ncodes,-9999). compute var = make(ncodes,ncodes,-9999). compute min = make(ncodes,ncodes,-9999). compute kappa = make(ncodes,ncodes,-9999). compute zkappa = make(ncodes,ncodes,-9999). compute pzkappa = make(ncodes,ncodes,1). compute n = ntrans + 1. compute nr = rowtots. compute nr(lastone(#d,1)) = nr(lastone(#d,1)) + 1. compute pnr = nr / n. * Warning message for specification error. do if ( adjacent=0 and any(diag(freqs)) = 1). print /title="WARNING". print /title="You have indicated that consecutive or adjacent codes can ". print /title="never repeat, (adjacent = 0), yet repeating codes have been ". print /title="found in the data. See the main diagonal of the frequency ". print /title="matrix. This specification error will result in faulty ". print /title="computations for LRX2, z-values, and adjusted residuals.". end if. loop #i = 1 to ncodes. loop #j = 1 to ncodes. * Note: more refined computations for when adjacent codes cannot repeat appear below, after the above 2 loops are completed. do if (adjacent = 0 and (ntrans - rowtots(#i,1)) > 0 ). compute pcols(1,#j) = coltots(1,#j) / (ntrans - rowtots(#i,1) ). end if. do if (adjacent = 0 and (ntrans - rowtots(#j,1)) > 0 ). compute expfreq(#i,#j) = ( rowtots(#i,1) * coltots(1,#j)) / (ntrans - rowtots(#j,1)). end if. do if (adjacent = 0 and (n - nr(#i,1)) > 0). compute et(#i,#j) = (nr(#i,1) * nr(#j,1)) / (n - nr(#i,1)) . end if. do if (adjacent = 1). compute et(#i,#j) = (nr(#i,1) * nr(#j,1)) / n. compute expfreq(#i,#j) = ( rowtots(#i,1) * coltots(1,#j)) / ntrans . end if. * transitional probabilities. do if (rowtots(#i,1) > 0). compute p(#i,#j) = freqs(#i,#j) / rowtots(#i,1) . end if. * tablewise LRX2. do if ( freqs(#i,#j) > 0 and expfreq(#i,#j)) > 0). compute lrx2t=lrx2t + 2 * (freqs(#i,#j) * ln(freqs(#i,#j)/expfreq(#i,#j))). end if. * LRX2 for stationarity/homogeneity. do if ( #d < nrow(each) ). do if ( rowtott(#i,1) > 0). compute pp(#i,#j) = freqst(#i,#j) / rowtott(#i,1) . end if. do if ( (p(#i,#j) > 0 and pp(#i,#j)) > 0). compute lrx2sh=lrx2sh+2*( freqs(#i,#j) * ln( p(#i,#j) / pp(#i,#j) ) ). end if. end if. * adjusted residuals (z values) & sig levels. do if ( (expfreq(#i,#j)*(1-pcols(1,#j))*(1-prows(#i,1))) > 0). compute zadjres(#i,#j)=(freqs(#i,#j)-expfreq(#i,#j)) /sqrt( expfreq(#i,#j)*(1-pcols(1,#j)) * (1-prows(#i,1)) ). compute pzadjres(#i,#j) = (1 - cdfnorm(abs(zadjres(#i,#j))) ) * tailed. end if. * Yule's Q; see Bakeman & Gottman, 1997, p 129. compute a = freqs(#i,#j). compute b = rowtots(#i,1) - freqs(#i,#j). compute c = coltots(1,#j) - freqs(#i,#j). compute d = ntrans - rowtots(#i,1) - coltots(1,#j) + freqs(#i,#j). do if ( (a*d + b*c) > 0 ). compute yulesq(#i,#j) = ( a*d - b*c ) / (a*d + b*c). end if. * kappas, z values & sig levels. compute var(#i,#j)=(nr(#i,1)*nr(#j,1)*(n-nr(#j,1))*(n-nr(#i,1)))/ (n**2*(n-1)). do if (var(#i,#j) > 0). compute zkappa(#i,#j) = ( freqs(#i,#j) - et(#i,#j) )/sqrt(var(#i,#j)). do if ( nr(#i,1) le nr(#j,1) ). compute min(#i,#j) = nr(#i,1). else. compute min(#i,#j) = nr(#j,1). end if. do if ( (min(#i,#j) - et(#i,#j)) ne 0). compute kappa(#i,#j) = ( freqs(#i,#j) - et(#i,#j) ) / ( min(#i,#j) - et(#i,#j) ). do if ( kappa(#i,#j) < 0 ). compute kappa(#i,#j) = ( freqs(#i,#j) - et(#i,#j) ) / et(#i,#j). end if. compute pzkappa(#i,#j) = (1 - cdfnorm(abs(zkappa(#i,#j)))) * tailed. end if. end if. end loop. end loop. do if (adjacent = 0 or adjacent = 2). * maximum likelihood estimation of the expected cell frequencies using iterative proportional fitting (Wickens, 1989, pp. 107-112). compute rsumsf = rsum(freqs). compute csumsf = csum(freqs). compute onezero = make(ncodes,ncodes,1). call setdiag(onezero,0). * the two previous commands create a matrix of ones and zeros that is used in estimating the expected cell frequencies. A "1" indicates that the expected frequency for a given cell is to be estimated, whereas a "0" indicates that the expected frequency for the cell should NOT be estimated, typically because it is a structural zero (codes that cannot follow one another). By default, the matrix that is created by the above commands has zeros along the main diagonal, and ones everywhere else, which will be appropriate for most data sets. However, if your data happen to involve structural zeros that occur in cells other than the cells along the main diagonal, then you must create a ONEZERO matrix with ones and zeros that is appropriate for your data before running any of the commands below. Enter your ONEZERO matrix now. compute expfreq = onezero. loop #ipfloop = 1 to 100. * adjusting by row. compute xr = make(ncodes,1,0). compute rsumse = rsum(expfreq). loop #r = 1 to ncodes. do if ( rsumse(#r,1) > 0). compute xr(#r,1) = rsumsf(#r,1) / rsumse(#r,1). end if. end loop. loop #i = 1 to ncodes. loop #j = 1 to ncodes. do if ( onezero(#i,#j) = 1 ). compute expfreq(#i,#j) = expfreq(#i,#j) * xr(#i,1). end if. end loop. end loop. * adjusting by collumn. compute xc = make(1,ncodes,0). compute csumse = csum(expfreq). loop #c = 1 to ncodes. do if ( csumse(1,#c) > 0). compute xc(1,#c) = csumsf(1,#c) / csumse(1,#c). end if. end loop. loop #i = 1 to ncodes. loop #j = 1 to ncodes. do if ( onezero(#i,#j) = 1 ). compute expfreq(#i,#j) = expfreq(#i,#j) * xc(1,#j). end if. end loop. end loop. compute rdiffs = rsumsf - rsum(expfreq). compute cdiffs = csumsf - csum(expfreq). end loop if ( mmax(rdiffs) < .0001 and mmax(cdiffs) < .0001). print / title="Maximum likelihood estimation of the expected cell". print / title="frequencies using iterative proportional fitting". do if ( mmax(rdiffs) < .0001 and mmax(cdiffs) < .0001). print #ipfloop/title="converged after the following number of interations:". else. print #ipfloop /title="did NOT converge after the following number of interations:". end if. * tablewise LRX2. compute lrx2t = {0}. loop #i = 1 to ncodes. loop #j = 1 to ncodes. do if ( freqs(#i,#j) > 0 and expfreq(#i,#j) > 0). compute lrx2t=lrx2t+2 * (freqs(#i,#j) * ln(freqs(#i,#j)/expfreq(#i,#j))). end if. end loop. end loop. * adjusted residuals for matrices with structural zeros (Christensen, 1997, p.357). * constructing the design matrix. compute x = make(ncodes**2,1,1). compute y = make(ncodes**2,ncodes-1,0). compute z = make(ncodes**2,ncodes-1,0). loop #i = 1 to ncodes - 1. loop #j = 1 to ncodes. compute y(#i*ncodes+#j,#i) = 1. compute z( (((#j-1)*ncodes)+(#i+1)),#i) = 1. end loop. end loop. compute des1 = { x, y, z }. * pruning values corresponding to cells with structural zeros. compute onezero2 = reshape(onezero,ncodes**2,1). compute dm1 = reshape(expfreq,ncodes**2,1). compute dm2 = make(1,1,-9999). compute des2 = make(1,ncol(des1),-9999). loop #p = 1 to ncodes**2. do if (onezero2(#p,1) = 1). compute dm2 = { dm2 ; dm1 (#p,1) }. compute des2 = { des2 ; des1(#p,:) }. end if. end loop. compute dm2 = dm2(2:nrow(dm2),1). compute des2 = des2(2:nrow(des2),:). compute dm2 = mdiag(dm2). do if ( det(t(des2) * dm2 * des2) ne 0). compute a = des2 * (inv(t(des2) * dm2 * des2)) * t(des2) * dm2. compute acounter = 1. loop #i = 1 to ncodes. loop #j = 1 to ncodes. do if ( onezero(#i,#j) ne 0). compute zadjres(#i,#j) = ( freqs(#i,#j) - expfreq(#i,#j) ) / sqrt( expfreq(#i,#j) * (1 - a(acounter,acounter)) ). compute acounter = acounter + 1. end if. end loop. end loop. else. print /space = 2. print /title="A nonsingular matrix has been identified, which means". print /title="that proper adjusted residuals cannot be computed for". print /title="this data, probably because there are no values for". print /title="one or more codes. Try recoding using sequential". print /title="integers, and redo the analyses. The adjusted". print /title="residuals that are printed below are based on". print /title="equation 5 from Bakeman & Quera (1995, p. 274), and". print /title="are close approximations to the proper values.". print /title="The procedures recommended by Bakeman & Quera". print /title="(1995, p. 276), Haberman (1979), and Christensen". print /title="(1997) cannot be conducted with nonsingular matrices.". end if. loop #i = 1 to ncodes. loop #j = 1 to ncodes. do if ( onezero(#i,#j) = 0). compute zadjres(#i,#j) = 0. compute yulesq (#i,#j) = 0. compute kappa (#i,#j) = 0. compute zkappa (#i,#j) = 0. compute pzadjres(#i,#j) = 1. compute pzkappa (#i,#j) = 1. end if. end loop. end loop. end if. do if (outfile = 1). compute outf = freqs. else if (outfile = 2). compute outf = p. else if (outfile = 3). compute outf = zadjres. else if (outfile = 4). compute outf = yulesq. else if (outfile = 5). compute outf = k. end if. compute out = { out; #d, (reshape(outf,1,(ncodes*ncodes))) }. compute b = labels(1,1:ncodes). do if (#d < nrow(each) and output = 2). print #d /title="Group/Segment Number:". else if (#d = nrow(each) ). print /title= "Pooled Data:" /space = 5. print {nrow(each)-1} /title="Number of cases/groups/segments:". compute dfsh = ncodes * (ncodes - 1) * ((nrow(each)-1) - 1). compute plrx2sh = 1 - chicdf(abs(lrx2sh),dfsh) . print { lrx2sh, dfsh, plrx2sh} /format "f12.4" /title ="Likelihood Ratio (Chi-Square) Test of Homogeneity/Stationarity" /cnames={"LRX2","df", "sig."}. end if. do if (#d = nrow(each) or output = 2). compute b = labels(1,1:ncodes). compute bb = { b,"Totals"}. print /space = 2. print tailed /title="Requested 'tail' (1 or 2) for Significance Tests =". print {freqs, rowtots; coltots, ntrans} /title="Cell Frequencies, Row & Collumn Totals, & N" /cnames=bb/rnames=bb. do if (adjacent = 0 or adjacent = 2). print /space = 1. print /title="The processed ONEZERO matrix appears below.". print /title="In the ONEZERO matrix, a 0 indicates a structural". print /title="zero, and a 1 indicates that an expected cell frequency". print /title="will be estimated.". print onezero /title="ONEZERO matrix:" /cnames=b/rnames=b. end if. print expfreq /format "f5.4" /title="Expected Values/Frequencies"/cnames=b/rnames=b. print p /format "f5.4" /title="Transitional Probabilities"/cnames=b/rnames=b. do if (adjacent = 1). compute dft = (ncodes - 1)**2. else. compute dft = (ncodes - 1)**2 - (ncodes**2 - msum(onezero)). end if. compute plrx2t = 1 - chicdf(abs(lrx2t),dft) . print { lrx2t, dft, plrx2t} /format "f12.4" /title="Tablewise Likelihood Ratio (Chi-Square) Test" /cnames={"LRX2","df", "sig."}. print tailed /title="Requested 'tail' (1 or 2) for Significance Tests =". print zadjres /format "f6.3" /title="Adjusted Residuals"/cnames=b/rnames=b. print pzadjres /format "f5.4" /title="Significance Levels for the Adjusted Residuals"/cnames=b/rnames=b. print yulesq /format "f6.3" /title="Yule's Q Values"/cnames=b/rnames=b. print kappa /format "f5.4" /title="Unidirectional Kappas"/cnames=b/rnames=b. print zkappa /format "f6.3" /title="z values for the Unidirectional Kappas"/cnames=b/rnames=b. print pzkappa /format "f5.4"/title= "Significance Levels for the Unidirectional Kappas"/cnames=b/rnames=b. end if. end loop. compute out = out(2:nrow(out),:). print out /title="Requested output data". * The following SAVE command will save the requested matrix output data in an SPSS system file. You must provide legal file and directory names for your system (e.g., 'C:\output.sav'), and then "activate" the SAVE command by removing the "*" that currently makes the command a mere comment. * save out / outfile ='Hard Disk:output.sav'. end matrix. * The requested output matrix has been reshaped into one long row of data. * get file='Hard Disk:output.sav' . * descriptives var= all.