diff --git a/applications/lazstats/source/forms/analysis/comparisons/withinanovaunit.lfm b/applications/lazstats/source/forms/analysis/comparisons/withinanovaunit.lfm index 865c16256..8d1d8722e 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/withinanovaunit.lfm +++ b/applications/lazstats/source/forms/analysis/comparisons/withinanovaunit.lfm @@ -186,13 +186,11 @@ inherited WithinANOVAFrm: TWithinANOVAFrm inherited ReportPage: TTabSheet Caption = 'ANOVA Results' end - object ReliabilityPage: TTabSheet[1] + object ReliabilityPage: TTabSheet[2] Caption = 'Reliability Estimates' end - object TestAssumptionsPage: TTabSheet[2] + object TestAssumptionsPage: TTabSheet[3] Caption = 'Test Assumptions' end - inherited ChartPage: TTabSheet[3] - end end end diff --git a/applications/lazstats/source/forms/analysis/comparisons/withinanovaunit.pas b/applications/lazstats/source/forms/analysis/comparisons/withinanovaunit.pas index 41ed3f0bc..e3891fa20 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/withinanovaunit.pas +++ b/applications/lazstats/source/forms/analysis/comparisons/withinanovaunit.pas @@ -16,6 +16,21 @@ type { TWithinANOVAFrm } + TWithinANOVAResults = record + // Sum of squares + SSRows, SScols, SSwithinRows, SStotal, SSresidual: Double; + // Mean square errors + MSRows, MScols, MSwithinRows, MStotal, MSresidual: Double; + // Degrees of freedom + DFRows, DFcols, DFWithinRows, DFtotal, DFresidual: Integer; + // Grand mean + GrandMean: Double; + // F value + F: Double; + // Probability for > F + Probability: Double; + end; + TWithinANOVAFrm = class(TBasicStatsReportAndChartForm) AssumpChk: TCheckBox; PlotChk: TCheckBox; @@ -38,8 +53,39 @@ type private FReliabilityReportFrame: TReportFrame; FTestAssumptionsReportFrame: TReportFrame; + + procedure CalcANOVA( + const ARowSums, ARowSumsOfSquares, AColSums, AColSumsOfSquares: DblDyneVec; + const AGrandSum, AGrandSumOfSquares: Double; + out ARowMeans, ARowVariances, AColMeans,AColVariances: DblDyneVec; + out AResults: TWithinANOVAResults); + + procedure CalcReliability(const AResults: TWithinANOVAResults; + ANumSelected: Integer; out R1, R2, R3, R4: Double); + + procedure GetData( + out ASelected: IntDyneVec; out AColLabels: StrDyneVec; + out ARowSums, ARowSumsOfSquares, AColSums, AColSumsOfSquares: DblDyneVec; + out AGrandSum, AGrandSumOfSquares: Double); + procedure Plot(ColMeans: DblDyneVec; ColLabels: StrDyneVec); - + + procedure TestAssumptions(const ASelected: IntDyneVec; + out ASampleVarCovarMat, AssumedVarCovarMat: DblDyneMat; + out ADeterminant1, ADeterminant2, Chi2, AProbability: Double; + out DF: Integer; out ErrorFound: Boolean); + + procedure WriteANOVAReport(const AColLabels: StrDyneVec; + const AColMeans, AColVariances: DblDyneVec; const AResults: TWithinANOVAResults); + + procedure WriteReliabilityReport(const R1, R2, R3, R4: Double); + + procedure WriteTestAssumptionsReport( + const ASampleVarCovarMat, AssumedVarCovarMat: DblDyneMat; + const AColLabels: StrDyneVec; + ADeterminant1, ADeterminant2, Chi2, AProbability: Double; DF: Integer; + ErrorFound: Boolean); + protected procedure AdjustConstraints; override; procedure Compute; override; @@ -62,7 +108,7 @@ implementation uses TAChartUtils, TACustomSeries, GridProcs, - Utils, MathUnit, ChartFrameUnit; + Utils, MathUnit, MatrixUnit, ChartFrameUnit; { TWithinANOVAFrm } @@ -109,88 +155,62 @@ begin end; -procedure TWithinANOVAFrm.Compute; +procedure TWithinANOVAFrm.CalcANOVA( + const ARowSums, ARowSumsOfSquares, AColSums, AColSumsOfSquares: DblDyneVec; + const AGrandSum, AGrandSumOfSquares: Double; + out ARowMeans, ARowVariances, AColMeans,AColVariances: DblDyneVec; + out AResults: TWithinANOVAResults); var - i, j, k, f3: integer; - NoSelected, count, row: integer; - SSrows, SScols, SSwrows, SSerr, SStot: double; - MSrows, MScols, MSwrows, MSerr, MStot: double; - dfrows, dfcols, dfwrows, dferr, dftot: double; - f1, probf1, GrandMean, Term1, Term2, Term3, Term4: double; - r1, r2, r3, r4, X, XSq, avgvar, avgcov: double; - determ1, determ2, M2, C2, chi2, prob: double; - errorfound: boolean; - Selected: IntDyneVec = nil; - ColLabels: StrDyneVec = nil; - ColMeans: DblDyneVec = nil; - ColVar: DblDyneVec = nil; - RowMeans: DblDyneVec = nil; - RowVar: DblDyneVec = nil; - ColStdDev: DblDyneVec = nil; - varcovmat: DblDyneMat = nil; - vcmat: dblDyneMat = nil; - workmat: DblDyneMat = nil; - title: string; - lReport: TStrings; + S: Double = 0; + SS: Double = 0; + term1, term2, term3, term4: Double; + noSelected: Integer; + i, count: Integer; + begin - errorfound := false; - NoSelected := SelList.Items.Count; + noSelected := SelList.Items.Count; + count := Length(ARowSums); - SetLength(Selected, NoSelected); - SetLength(ColLabels, NoSelected); - SetLength(ColMeans, NoSelected); - SetLength(ColVar, NoSelected); - SetLength(RowMeans, NoCases); - SetLength(RowVar, NoCases); + term1 := sqr(AGrandSum) / (count * noSelected); - for i := 0 to NoSelected - 1 do - begin - Selected[i] := GetVariableIndex(OS3MainFrm.DataGrid, SelList.Items[i]); - ColLabels[i] := SelList.Items[i]; - end; + term2 := AGrandSumOfSquares; - // Initialize values - SScols := 0.0; - SSrows := 0.0; - SStot := 0.0; - dfwrows := 0.0; - dftot := 0.0; - GrandMean := 0.0; - count := 0; + SS := 0; + for i := 0 to count-1 do + SS := SS + sqr(ARowSums[i]); + term4 := SS / noSelected; - for i := 0 to NoSelected-1 do - begin - ColMeans[i] := 0.0; - ColVar[i] := 0.0; - end; - for j := 0 to NoCases-1 do - begin - RowMeans[j] := 0.0; - RowVar[j] := 0.0; - end; + SS := 0; + for i := 0 to noSelected-1 do + SS := SS + sqr(AColSums[i]); + term3 := SS / count; + + AResults.SSrows := term4 - term1; + AResults.SScols := term3 - term1; + AResults.SSwithinRows := term2 - term4; + AResults.SSresidual := term2 - term3 - term4 + term1; + AResults.SStotal := term2 - term1; + + AResults.DFrows := count - 1; + AResults.DFcols := noSelected - 1; + AResults.DFwithinRows := count * (noSelected - 1); + AResults.DFresidual := (count - 1) * (noSelected - 1); + AResults.DFtotal := count * noSelected - 1; + + AResults.MSrows := AResults.SSrows / AResults.DFRows; + AResults.MScols := AResults.SScols / AResults.DFcols; + AResults.MSwithinRows := AResults.SSwithinRows / AResults.DFwithinRows; + AResults.MSresidual := AResults.SSresidual / AResults.DFresidual; + AResults.MStotal := AResults.SStotal / AResults.DFtotal; // variance of all scores + + AResults.GrandMean := AGrandSum / (count * noSelected); + (* + AResults.SSRows := VecSum(ARowMeans); + + term1 := sqr(AGrandSum) / (count * noSelected); + term2 := AGrandSumOfSquares); - // Read data and compute sums while reading - row := 0; - for i := 1 to NoCases do - begin - if not GoodRecord(OS3MainFrm.DataGrid, i, Selected) then continue; - count := count + 1; - for j := 1 to NoSelected do - begin - k := Selected[j-1]; - X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i])); - Xsq := X*X; - RowMeans[row] := RowMeans[row] + X; - RowVar[row] := RowVar[row] + Xsq; - ColMeans[j-1] := ColMeans[j-1] + X; - ColVar[j-1] := ColVar[j-1] + Xsq; - GrandMean := GrandMean + X; - SStot := SStot + XSq; - end; - row := row + 1; - end; - // Calculate ANOVA results Term1 := sqr(GrandMean) / (count * NoSelected); Term2 := SStot; for i := 0 to count-1 do @@ -229,185 +249,178 @@ begin end; f1 := MScols / MSerr; // treatment F statistic probf1 := ProbF(f1, dfcols, dferr); + *) + + SetLength(ARowMeans, count); + SetLength(ARowVariances, count); + for i := 0 to count-1 do + begin + ARowVariances[i] := (ARowSumsOfSquares[i] - (ARowSums[i] * ARowSums[i]) / noSelected) / (noSelected - 1); + ARowMeans[i] := ARowSums[i] / noSelected; + end; + + SetLength(AColMeans, noSelected); + SetLength(AColVariances, noSelected); + for i := 0 to noSelected-1 do + begin + AColVariances[i] := (AColSumsOfSquares[i] - (AColSums[i] * AColSums[i]) / count) / (count - 1); + AColMeans[i] := AColSums[i] / count; + end; + + with AResults do + begin + F := MScols / MSresidual; // treatment F statistic + Probability := ProbF(F, DFcols, DFresidual); + end; + end; + + +procedure TWithinANOVAFrm.CalcReliability(const AResults: TWithinANOVAResults; + ANumSelected: Integer; out R1, R2, R3, R4: Double); +begin + with AResults do + begin + // unadjusted reliability of test + R1 := 1.0 - (MSwithinRows / MSrows); + + // R2 is unadjusted reliability of a single item + R2 := (MSrows - MSwithinRows) / (MSrows + (ANumSelected - 1) * MSwithinRows); + + // Cronbach alpha for test + R3 := (MSrows - MSresidual) / MSrows; + + // R4 is adjusted reliability of a single item + R4 := (MSrows - MSresidual) / (MSrows + (ANumSelected - 1) * MSresidual); + end; +end; + + +procedure TWithinANOVAFrm.Compute; +var + j, noSelected, DF: integer; + r1, r2, r3, r4: double; + grandSum, grandSS: Double; + determ1, determ2, chi2, prob: Double; + errorfound: boolean; + selected: IntDyneVec = nil; + colLabels: StrDyneVec = nil; + colSums: DblDyneVec = nil; + colMeans: DblDyneVec = nil; + colSS: DblDyneVec = nil; + colVars: DblDyneVec = nil; + rowSums: DblDyneVec = nil; + rowMeans: DblDyneVec = nil; + rowSS: DblDyneVec = nil; + rowVars: DblDyneVec = nil; + sampleVarCovarMat: DblDyneMat = nil; + assumedVarCovarMat: DblDyneMat = nil; + res: TWithinANOVAResults; +begin + noSelected := SelList.Items.Count; + + // Read data and compute sums while reading + GetData(selected, colLabels, rowSums, rowSS, colSums, colSS, grandSum, grandSS); + + // Calculate ANOVA + CalcANOVA(rowSums, rowSS, colSums, colSS, grandSum, grandSS, rowMeans, rowVars, colMeans, colVars, res); + WriteANOVAReport(colLabels, colMeans, colVars, res); // Do reliability terms if requested if RelChk.Checked then begin - r1 := 1.0 - (MSwrows / MSrows); // unadjusted reliability of test - r2 := (MSrows - MSwrows) / (MSrows + (NoSelected - 1) * MSwrows); - // r2 is unadjusted reliability of a single item - r3 := (MSrows - MSerr) / MSrows; // Cronbach alpha for test - r4 := (MSrows - MSerr) / (MSrows + (NoSelected - 1) * MSerr); - // r4 is adjusted reliability of a single item - end; - - // do homogeneity of variance and covariance checks if requested - - lReport := TStringList.Create; - try - // print results - lReport.Add('TREATMENTS BY SUBJECTS (AxS) ANOVA RESULTS'); - lReport.Add(''); - lReport.Add('Data File: ' + OS3MainFrm.FileNameEdit.Text); - lReport.Add(''); - lReport.Add(''); - lReport.Add('-----------------------------------------------------------'); - lReport.Add('SOURCE DF SS MS F Prob. > F'); - lReport.Add('-----------------------------------------------------------'); - lReport.Add('SUBJECTS %4.0f%10.3f%10.3f', [dfrows, SSrows, MSrows]); - lReport.Add('WITHIN SUBJECTS%4.0f%10.3f%10.3f', [dfwrows, SSwrows, MSwrows]); - lReport.Add(' TREATMENTS %4.0f%10.3f%10.3f%10.3f%10.3f', [dfcols, SScols, MScols, f1, probf1]); - lReport.Add(' RESIDUAL %4.0f%10.3f%10.3f', [dferr, SSerr, MSerr]); - lReport.Add('-----------------------------------------------------------'); - lReport.Add('TOTAL %4.0f%10.3f%10.3f', [dftot, SStot, MStot]); - lReport.Add('-----------------------------------------------------------'); - lReport.Add(''); - lReport.Add(''); - lReport.Add('TREATMENT (COLUMN) MEANS AND STANDARD DEVIATIONS'); - lReport.Add('VARIABLE MEAN STD.DEV. '); - lReport.Add('-------- ---------- ----------'); - for i := 1 to NoSelected do - lReport.Add('%-8s %10.3f %10.3f', [ColLabels[i-1], ColMeans[i-1], sqrt(ColVar[i-1])]); - lReport.Add(''); - lReport.Add('Mean of all scores: %8.3f', [GrandMean]); - lReport.Add(' with standard deviation: %8.3f', [sqrt(MStot)]); - - FReportFrame.DisplayReport(lReport); - - // Do reliability estimates if requested - if RelChk.Checked then - begin - lReport.Clear; - lReport.Add('RELIABILITY ESTIMATES'); - lReport.Add(''); - lReport.Add('TYPE OF ESTIMATE VALUE '); - lReport.Add('---------------------------- -------'); - lReport.Add('Unadjusted total reliability %7.3f', [r1]); - lReport.Add('Unadjusted item reliability %7.3f', [r2]); - lReport.Add('Adjusted total (Cronbach) %7.3f', [r3]); - lReport.Add('Adjusted item reliability %7.3f', [r4]); - FReliabilityReportFrame.DisplayReport(lReport); - end; + CalcReliability(res, noSelected, r1, r2, r3, r4); + WriteReliabilityReport(r1, r2, r3, r4); ReliabilityPage.TabVisible := RelChk.Checked; - - // Test assumptions of variance - covariance homogeneity if requested - if AssumpChk.Checked then - begin - SetLength(varcovmat,NoSelected+1,NoSelected+1); - SetLength(vcmat,NoSelected+1,NoSelected+1); - SetLength(workmat,NoSelected+1,NoSelected+1); - SetLength(ColStdDev,NoSelected); - errorfound := false; - count := NoCases; - lReport.Clear; - lReport.Add('BOX TEST FOR HOMOGENEITY OF VARIANCE-COVARIANCE MATRIX'); - lReport.Add(''); - GridCovar(NoSelected, Selected, varcovmat, ColMeans, ColVar, ColStdDev, errorfound, count); - title := 'SAMPLE COVARIANCE MATRIX'; - MatPrint(varcovmat, NoSelected, NoSelected, title, ColLabels, ColLabels, NoCases, lReport); - if errorfound then - ErrorMsg('Zero variance found for a variable.'); - - // get average of variances into workmat diagonal and average of - // covariances into workmat off-diagonals (See Winer, pg 371) - avgvar := 0.0; - avgcov := 0.0; - for i := 0 to NoSelected-1 do - vcmat[i,i] := varcovmat[i,i]; - for i := 0 to NoSelected-2 do - begin - for j := i+1 to NoSelected-1 do - begin - vcmat[i,j] := varcovmat[i,j]; - vcmat[j,i] := vcmat[i,j]; - end; - end; - - for i := 0 to NoSelected-1 do - avgvar := avgvar + varcovmat[i,i]; - for i := 0 to NoSelected-2 do - for j := i+1 to NoSelected-1 do - avgcov := avgcov + varcovmat[i,j]; - avgvar := avgvar / NoSelected; - avgcov := avgcov / (NoSelected * NoSelected - 1) / 2.0; - for i := 0 to NoSelected-1 do - workmat[i,i] := avgvar; - for i := 0 to NoSelected-2 do - begin - for j := i+1 to NoSelected-1 do - begin - workmat[i,j] := avgcov; - workmat[j,i] := workmat[i,j]; - end; - end; - - // get determinants of varcov and workmat - determ1 := 0.0; - determ2 := 0.0; - M2 := 0.0; - C2 := 0.0; - chi2 := 0.0; - prob := 0.0; - Determ(vcmat,NoSelected,NoSelected,determ1,errorfound); - if determ1 < 0.0 then determ1 := 0.0; - Determ(workmat,NoSelected,NoSelected,determ2,errorfound); - if determ2 < 0.0 then determ2 := 0.0; - count := NoCases; - GridCovar(NoSelected,Selected,varcovmat,ColMeans,ColVar,ColStdDev,errorfound,count); - errorfound := false; - if ((determ1 > 0.0) and (determ2 > 0.0)) then - M2 := -(NoCases*NoSelected - 1) * ln(determ1 / determ2) - else - begin - M2 := 0.0; - errorfound := true; - ErrorMsg('A determinant <= zero was found.'); - end; - if not errorfound then - begin - C2 := NoSelected * (NoSelected+1) * (NoSelected + 1) * (2 * NoSelected - 3); - C2 := C2 / (6 * (count - 1)*(NoSelected - 1) * (NoSelected * NoSelected + NoSelected - 4)); - chi2 := (1.0 - C2) * M2; - f3 := (NoSelected * NoSelected + NoSelected - 4) div 2; - if ((chi2 > 0.01) and (chi2 < 1000.0)) then - prob := chisquaredprob(chi2,f3) - else - begin - if chi2 <= 0.0 then prob := 1.0; - if chi2 >= 1000.0 then prob := 0.0; - end; - end; - - title := 'ASSUMED POP. COVARIANCE MATRIX'; - for i := 0 to NoSelected-1 do - for j := 0 to NoSelected-1 do - varcovmat[i,j] := workmat[i,j]; - MatPrint(varcovmat, NoSelected, NoSelected, title, ColLabels, ColLabels, NoCases, lReport); - lReport.Add('Determinant of variance-covariance matrix: %10.3g', [determ1]); - lReport.Add('Determinant of homogeneity matrix: %10.3g', [determ2]); - if not errorfound then - begin - lReport.Add('ChiSquare: %10.3f', [chi2]); - lReport.Add(' with %d degrees of freedom', [f3]); - lReport.Add('Probability of larger chisquare: %10.3f', [1.0-prob]); - end; - - FTestAssumptionsReportFrame.DisplayReport(lReport); - end; - TestAssumptionsPage.TabVisible := AssumpChk.Checked; - - finally - lReport.Free; end; - { Finally, plot values if indicated in options list } + // Test assumptions of variance - covariance homogeneity if requested + if AssumpChk.Checked then + begin + TestAssumptions(selected, sampleVarCovarMat, assumedVarCovarMat, determ1, determ2, chi2, prob, DF, errorFound); + WriteTestAssumptionsReport(sampleVarCovarMat, assumedVarCovarMat, colLabels, determ1, determ2, chi2, prob, DF, errorFound); + end; + TestAssumptionsPage.TabVisible := AssumpChk.Checked; + + // Finally, plot values if indicated in options list if PlotChk.Checked then Plot(ColMeans, ColLabels); ChartPage.TabVisible := PlotChk.Checked; + + // Make sure that the chart tab is at the end of the pagecontrol. ChartPage.PageIndex := PageControl.PageCount-1; end; +procedure TWithinANOVAFrm.GetData( + out ASelected: IntDyneVec; out AColLabels: StrDyneVec; + out ARowSums, ARowSumsOfSquares, AColSums, AColSumsOfSquares: DblDyneVec; + out AGrandSum, AGrandSumOfSquares: Double); +var + i, j, row, count, noSelected: Integer; + k: Integer; + X, Xsq: Double; +begin + ARowSums := nil; // to silence FPC 3.2 + ARowSumsOfSquares := nil; + AColSums := nil; + AColSumsOfSquares := nil; + AColLabels := nil; + ASelected := nil; + + noSelected := SelList.Items.Count; + SetLength(ASelected, noSelected); + SetLength(AColLabels, noSelected); + SetLength(AColSums, noSelected); + SetLength(AColSumsOfSquares, noSelected); + SetLength(ARowSums, NoCases); + SetLength(ARowSumsOfSquares, NoCases); + + for i := 0 to noSelected-1 do + begin + ASelected[i] := GetVariableIndex(OS3MainFrm.DataGrid, SelList.Items[i]); + AColLabels[i] := SelList.Items[i]; + end; + + for i := 0 to noSelected-1 do + begin + AColSums[i] := 0.0; + AColSumsOfSquares[i] := 0.0; + end; + for j := 0 to NoCases-1 do + begin + ARowSums[j] := 0.0; + ARowSumsOfSquares[j] := 0.0; + end; + + AGrandSum := 0; + AGrandSumOfSquares := 0; + count := 0; + row := 0; + + for i := 1 to NoCases do + begin + if not GoodRecord(OS3MainFrm.DataGrid, i, ASelected) then continue; + count := count + 1; + for j := 0 to High(ASelected) do + begin + k := ASelected[j]; + X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k, i])); + Xsq := X*X; + ARowSums[row] := ARowSums[row] + X; + ARowSumsOfSquares[row] := ARowSumsOfSquares[row] + Xsq; + AColSums[j] := AColSums[j] + X; + AColSumsOfSquares[j] := AColSumsOfSquares[j] + Xsq; + AGrandSum := AGrandSum + X; + AGrandSumOfSquares := AGrandSumOfSquares + XSq; + end; + row := row + 1; + end; + + SetLength(ARowSums, count); + SetLength(ARowSumsOfSquares, count); + // Lengths of AColSums etc already correct. +end; + procedure TWithinANOVAFrm.InBtnClick(Sender: TObject); var i: integer; @@ -506,6 +519,121 @@ begin end; +procedure TWithinANOVAFrm.TestAssumptions(const ASelected: IntDyneVec; + out ASampleVarCovarMat, AssumedVarCovarMat: DblDyneMat; + out ADeterminant1, ADeterminant2, Chi2, AProbability: Double; + out DF: Integer; out ErrorFound: Boolean); +var + vcMat: DblDyneMat = nil; + workMat: DblDyneMat = nil; + colMeans: DblDyneVec = nil; + colVars: DblDyneVec = nil; + colStdDevs: DblDyneVec = nil; + avgVar, avgCov, C2, M2: Double; + i, j, noSelected, count: Integer; +begin + ErrorFound := false; + noSelected := Length(ASelected); + count := NoCases; + + DF := 0; + Chi2 := NaN; + AProbability := NaN; + + SetLength(ASampleVarCovarMat, noSelected+1, noSelected+1); // +1 due to augmentation in GridCovar + SetLength(AssumedVarCovarMat, noSelected+1, noSelected+1); + SetLength(vcMat, noSelected+1, noSelected+1); + SetLength(workMat, noSelected+1, noSelected+1); + SetLength(colMeans, noSelected+1); + SetLength(colVars, noSelected+1); + SetLength(colStdDevs, noSelected+1); + + GridCovar(noSelected, ASelected, ASampleVarCovarMat, colMeans, colVars, colStdDevs, ErrorFound, count); + if Errorfound then + begin + ErrorMsg('Zero variance found for a variable.'); + exit; + end; + + // get average of variances into workmat diagonal and average of + // covariances into workmat off-diagonals (See Winer, pg 371) + avgVar := 0.0; + avgCov := 0.0; + for i := 0 to noSelected-1 do + vcMat[i, i] := ASampleVarCovarMat[i,i]; + + for i := 0 to noSelected-2 do + begin + for j := i+1 to noSelected-1 do + begin + vcMat[i, j] := ASampleVarCovarMat[i, j]; + vcMat[j, i] := vcMat[i, j]; + end; + end; + + for i := 0 to noSelected-1 do + avgVar := avgVar + ASampleVarCovarMat[i, i]; + + for i := 0 to NoSelected-2 do + for j := i+1 to NoSelected-1 do + avgCov := avgCov + ASampleVarCovarMat[i, j]; + + avgVar := avgVar / noSelected; + avgCov := avgCov / (noSelected * noSelected - 1) / 2.0; + + for i := 0 to noSelected-1 do + workMat[i, i] := avgVar; + + for i := 0 to noSelected-2 do + begin + for j := i+1 to noSelected-1 do + begin + workMat[i, j] := avgCov; + workMat[j, i] := workMat[i, j]; + end; + end; + + // get determinants of SampleVarCovarMat and workMat + Determ(vcMat, noSelected, noSelected, ADeterminant1, ErrorFound); + if ADeterminant1 < 0.0 then ADeterminant1 := 0.0; + + Determ(workMat, noSelected, noSelected, ADeterminant2, ErrorFound); + if ADeterminant2 < 0.0 then ADeterminant2 := 0.0; + + // Get assumed var-covariance matrix + count := NoCases; + GridCovar(noSelected, ASelected, AssumedVarCovarMat, colMeans, colVars, colStdDevs, ErrorFound, count); + ErrorFound := false; + if ((ADeterminant1 > 0.0) and (ADeterminant2 > 0.0)) then + M2 := -(NoCases*noSelected - 1) * ln(ADeterminant1 / ADeterminant2) + else + begin + M2 := 0.0; + errorFound := true; + ErrorMsg('A determinant <= zero was found.'); + end; + + if not ErrorFound then + begin + C2 := noSelected * (noSelected+1) * (noSelected + 1) * (2 * noSelected - 3); + C2 := C2 / (6 * (count - 1) * (noSelected - 1) * (noSelected * noSelected + noSelected - 4)); + Chi2 := (1.0 - C2) * M2; + DF := (noSelected * noSelected + noSelected - 4) div 2; + if ((Chi2 > 0.01) and (Chi2 < 1000.0)) then + AProbability := ChiSquaredProb(Chi2, DF) + else + begin + if Chi2 <= 0.0 then AProbability := 1.0; + if Chi2 >= 1000.0 then AProbability := 0.0; + end; + end; + + for i := 0 to NoSelected-1 do + for j := 0 to NoSelected-1 do + AssumedVarCovarMat[i,j] := workMat[i, j]; +end; + + procedure TWithinANOVAFrm.UpdateBtnStates; var i: Integer; @@ -580,5 +708,118 @@ begin end; +{ Write ANOVA results to ReportFrame } +procedure TWithinANOVAFrm.WriteANOVAReport(const AColLabels: StrDyneVec; + const AColMeans, AColVariances: DblDyneVec; const AResults: TWithinANOVAResults); +var + lReport: TStrings; + noSelected: Integer; + i: Integer; +begin + noSelected := Length(AColMeans); + + lReport := TStringList.Create; + try + with AResults do + begin + lReport.Add('TREATMENTS BY SUBJECTS (AxS) ANOVA RESULTS'); + lReport.Add(''); + lReport.Add('Data File: ' + OS3MainFrm.FileNameEdit.Text); + lReport.Add(''); + lReport.Add('-----------------------------------------------------------------'); + lReport.Add('SOURCE DF SS MS F Prob. > F'); + lReport.Add('-----------------------------------------------------------------'); + lReport.Add('SUBJECTS %4d %10.3f %10.3f', [DFrows, SSrows, MSrows]); + lReport.Add('WITHIN SUBJECTS %4d %10.3f %10.3f', [DFwithinRows, SSwithinRows, MSwithinRows]); + lReport.Add(' TREATMENTS %4d %10.3f %10.3f %10.3f %10.3f', [DFcols, SScols, MScols, F, Probability]); + lReport.Add(' RESIDUAL %4d %10.3f %10.3f', [DFresidual, SSresidual, MSresidual]); + lReport.Add('-----------------------------------------------------------------'); + lReport.Add('TOTAL %4d %10.3f %10.3f', [DFtotal, SStotal, MStotal]); + lReport.Add('-----------------------------------------------------------------'); + lReport.Add(''); + lReport.Add(''); + + lReport.Add('TREATMENT (COLUMN) MEANS AND STANDARD DEVIATIONS'); + lReport.Add(''); + lReport.Add('VARIABLE MEAN STD.DEV. '); + lReport.Add('-------- ---------- ----------'); + + for i := 1 to NoSelected do + lReport.Add('%-8s %10.3f %10.3f', [AColLabels[i-1], AColMeans[i-1], sqrt(AColVariances[i-1])]); + + lReport.Add(''); + lReport.Add('Mean of all scores: %8.3f', [GrandMean]); + lReport.Add(' with standard deviation: %8.3f', [sqrt(MStotal)]); + end; + + FReportFrame.DisplayReport(lReport); + finally + lReport.Free; + end; +end; + + +procedure TWithinANOVAFrm.WriteReliabilityReport(const R1, R2, R3, R4: double); +var + lReport: TStrings; +begin + lReport := TStringList.Create; + try + lReport.Add('RELIABILITY ESTIMATES'); + lReport.Add(''); + lReport.Add('TYPE OF ESTIMATE VALUE '); + lReport.Add('---------------------------- -------'); + lReport.Add('Unadjusted total reliability %7.3f', [R1]); + lReport.Add('Unadjusted item reliability %7.3f', [R2]); + lReport.Add('Adjusted total (Cronbach) %7.3f', [R3]); + lReport.Add('Adjusted item reliability %7.3f', [R4]); + + FReliabilityReportFrame.DisplayReport(lReport); + finally + lReport.Free; + end; +end; + + +procedure TWithinANOVAFrm.WriteTestAssumptionsReport( + const ASampleVarCovarMat, AssumedVarCovarMat: DblDyneMat; + const AColLabels: StrDyneVec; + ADeterminant1, ADeterminant2, Chi2, AProbability: Double; DF: Integer; + ErrorFound: Boolean); +var + lReport: TStrings; + title: String; + noSelected: Integer; +begin + noSelected := SelList.Items.Count; + + lReport := TStringList.Create; + try + lReport.Add('BOX TEST FOR HOMOGENEITY OF VARIANCE-COVARIANCE MATRIX'); + lReport.Add(''); + + title := 'SAMPLE COVARIANCE MATRIX'; + MatPrint(ASampleVarCovarMat, noSelected, noSelected, title, AColLabels, AColLabels, NoCases, lReport); + lReport.Add(''); + + title := 'ASSUMED POPULATION COVARIANCE MATRIX'; + MatPrint(AssumedVarCovarMat, noSelected, noSelected, title, AColLabels, AColLabels, NoCases, lReport); + lReport.Add(''); + + lReport.Add('Determinant of variance-covariance matrix: %10.3g', [ADeterminant1]); + lReport.Add('Determinant of homogeneity matrix: %10.3g', [ADeterminant2]); + if not errorfound then + begin + lReport.Add('ChiSquare: %10.3f', [Chi2]); + lReport.Add(' with %d degrees of freedom', [DF]); + lReport.Add('Probability of larger chisquare: %10.3f', [1.0 - AProbability]); + end; + + FTestAssumptionsReportFrame.DisplayReport(lReport); + finally + lReport.Free; + end; +end; + end.