diff --git a/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.lfm b/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.lfm index 32d3c6264..1fa02683d 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.lfm +++ b/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.lfm @@ -13,7 +13,31 @@ inherited ABRAnovaForm: TABRAnovaForm Width = 329 ClientHeight = 336 ClientWidth = 329 - object OptionsGroup: TGroupBox[0] + inherited CloseBtn: TButton + Left = 274 + Top = 311 + TabOrder = 14 + end + inherited ComputeBtn: TButton + Left = 190 + Top = 311 + TabOrder = 13 + end + inherited ResetBtn: TButton + Left = 128 + Top = 311 + TabOrder = 12 + end + inherited HelpBtn: TButton + Left = 69 + Top = 311 + TabOrder = 11 + end + inherited ButtonBevel: TBevel + Top = 295 + Width = 329 + end + object OptionsGroup: TGroupBox[5] AnchorSideLeft.Control = ParamsPanel AnchorSideBottom.Control = ButtonBevel Left = 0 @@ -70,30 +94,6 @@ inherited ABRAnovaForm: TABRAnovaForm TabOrder = 2 end end - inherited CloseBtn: TButton[1] - Left = 274 - Top = 311 - TabOrder = 14 - end - inherited ComputeBtn: TButton[2] - Left = 190 - Top = 311 - TabOrder = 13 - end - inherited ResetBtn: TButton[3] - Left = 128 - Top = 311 - TabOrder = 12 - end - inherited HelpBtn: TButton[4] - Left = 69 - Top = 311 - TabOrder = 11 - end - inherited ButtonBevel: TBevel[5] - Top = 295 - Width = 329 - end object Label1: TLabel[6] AnchorSideLeft.Control = ParamsPanel AnchorSideTop.Control = ParamsPanel @@ -331,15 +331,15 @@ inherited ABRAnovaForm: TABRAnovaForm inherited ReportPage: TTabSheet Caption = 'ANOVA Summary' end - object MeansPage: TTabSheet[1] + inherited ChartPage: TTabSheet + Caption = 'Charts' + end + object MeansPage: TTabSheet[2] Caption = 'Means' end - object BoxTestsPage: TTabSheet[2] + object BoxTestsPage: TTabSheet[3] Caption = 'Box Tests' end - inherited ChartPage: TTabSheet[3] - Caption = 'Charts' - end end object ListChartSource_AB: TListChartSource[3] Left = 465 diff --git a/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.pas b/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.pas index 1627c24ee..f102c0d95 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.pas +++ b/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.pas @@ -15,6 +15,38 @@ uses type + TABRAnovaData = record + // Counts + NoAGrps, NoBGrps, NInGrp, TotalN: Integer; + Acnt, Bcnt, Ccnt: IntDyneVec; + + // Degrees of freedom + DFA, DFB, DFC, DFAB, DFAC, DFBC, DFABC, DFBetween: double; + DFerrorBetween, DFWithin, DFerrorWithin: double; + + // Sums + ASums, BSums, CSums, SumPSqr: DblDyneVec; + ABSums, ACSums, BCSums: DblDyneMat; + ABCSums: DblDyneCube; + ABCNcnt: IntDyneCube; + GrandTotal: Double; + + // Sums of squares + SSA, SSB, SSC, SSAB, SSAC, SSBC, SSABC: Double; + SSBetweenSubjects, SSWithinSubjects: Double; + SSerrorBetween, SSerrorWithin: Double; + SumXSqr: Double; + + // Mean standard errors + MSA, MSB, MSC, MSAB, MSAC, MSBC, MSABC, MSerrorBetween, MSerrorWithin: Double; + + // F values + FA, FB, FC, FAB, FAC, FBC, FABC: Double; + + // Probabilities + ProbA, ProbB, ProbC, ProbAB, ProbAC, ProbBC, ProbABC: Double; + end; + { TABRAnovaForm } TABRAnovaForm = class(TBasicStatsReportAndChartForm) @@ -54,43 +86,32 @@ type procedure PlotChkChange(Sender: TObject); procedure ThreeDChkChange(Sender: TObject); procedure VarListDblClick(Sender: TObject); + private type TInteraction = (AB, AC, BC); private ColNoSelected: IntDyneVec; - ACol, BCol, NoSelected, MinA, MaxA, MinB, MaxB, NoAGrps, NoBGrps : integer; - group, MaxRows, MaxCols, TotalN, NinGrp : integer; - SubjTot, GrandTotal, SumXSqr : double; - DFA, DFB, DFC, DFAB, DFAC, DFBC, DFABC, DFBetween : double; - DFerrorBetween, DFWithin, DFerrorWithin : double; - SSA, SSB, SSC, SSAB, SSAC, SSBC, SSABC, SSBetweenSubjects : double; - SSerrorBetween, SSWithinSubjects, SSerrorWithin : double; - MSA, MSB, MSC, MSAB, MSAC, MSBC, MSABC, MSerrorBetween, MSerrorWithin : double; - FA, FB, FC, FAB, FAC, FBC, FABC : double; - ProbA, ProbB, ProbC, ProbAB, ProbAC, ProbBC, ProbABC : double; - Acnt, Bcnt, Ccnt : IntDyneVec; - ASums, BSums, CSums, SumPSqr : DblDyneVec; - ABSums, ACSums, BCSums: DblDyneMat; - ABCSums: DblDyneCube; - ABCNcnt: IntDyneCube; - selected : integer; + ACol, BCol, NoSelected, MinA, MaxA, MinB, MaxB: integer; + MaxRows, MaxCols: integer; + selected: Integer; FMeansReportFrame: TReportFrame; FBoxTestsReportFrame: TReportFrame; FBtnAB, FBtnAC, FBtnBC: TToolButton; FBarSeries: TBarSeries; procedure InteractionChanged(Sender: TObject); + procedure Set3DPlot(AEnable: Boolean); - function InitData: Boolean; - procedure GetData; - procedure Calculate; - procedure Summarize(AReport: TStrings); - procedure MeansReport(AReport: TStrings); - procedure BoxTests(AReport: TStrings); - procedure PreparePlot; + function InitData(out AData: TABRAnovaData): Boolean; + procedure GetData(var AData: TABRAnovaData); + procedure Calculate(var AData: TABRAnovaData); + procedure Summarize(const AData: TABRAnovaData; AReport: TStrings); + procedure MeansReport(const AData: TABRAnovaData; AReport: TStrings); + procedure BoxTests(const AData: TABRAnovaData; AReport: TStrings); + procedure PreparePlot(const AData: TABRAnovaData); procedure PlotMeans(AInteraction: TInteraction); - procedure CleanUp; + procedure CleanUp(var AData: TABRAnovaData); protected procedure AdjustConstraints; override; @@ -268,23 +289,26 @@ begin end; -procedure TABRAnovaForm.CleanUp; +procedure TABRAnovaForm.CleanUp(var AData: TABRAnovaData); begin - ABCNcnt := nil; - ABCSums := nil; - Ccnt := nil; - Bcnt := nil; - Acnt := nil; - SumPSqr := nil; - //{ - BCSums := nil; // needed for plotting - ACSums := nil; - ABSums := nil; - //} - CSums := nil; - BSums := nil; - ASums := nil; - ColNoSelected := nil; + with AData do + begin + ABCNcnt := nil; + ABCSums := nil; + Ccnt := nil; + Bcnt := nil; + Acnt := nil; + SumPSqr := nil; + //{ + BCSums := nil; // needed for plotting + ACSums := nil; + ABSums := nil; + //} + CSums := nil; + BSums := nil; + ASums := nil; + ColNoSelected := nil; + end; end; @@ -312,27 +336,28 @@ procedure TABRAnovaForm.Compute; var lReport: TStrings; interaction: TInteraction; + data: TABRAnovaData; begin lReport := TStringList.Create; try - if InitData then + if InitData(data) then begin - GetData; - Calculate; - Summarize(lReport); - MeansReport(lReport); + GetData(data); + Calculate(data); + Summarize(data, lReport); + MeansReport(data, lReport); BoxTestsPage.TabVisible := TestChk.Checked; if TestChk.Checked then begin - BoxTests(lReport); + BoxTests(data, lReport); //BoxTestsPage.PageIndex := 2; end; ChartPage.TabVisible := PlotChk.Checked; if PlotChk.Checked then begin - PreparePlot; + PreparePlot(data); if FBtnAB.Down then interaction := AB else if FBtnAC.Down then interaction := AC else if FBtnBC.Down then interaction := BC; @@ -342,7 +367,7 @@ begin end; finally lReport.Free; - CleanUp; + CleanUp(data); end; end; @@ -366,23 +391,17 @@ begin UpdateBtnStates; end; + procedure TABRAnovaForm.PlotChkChange(Sender: TObject); begin ThreeDChk.Enabled := PlotChk.Checked; end; -procedure TABRAnovaForm.ThreeDChkChange(Sender: TObject); -const - DEPTH: array[boolean] of Integer = (0, 20); -begin - FBarSeries.Depth := DEPTH[ThreeDChk.Checked]; - FChartFrame.Chart.LeftAxis.Grid.Visible := not ThreeDChk.Checked; -end; - -function TABRAnovaForm.InitData: Boolean; +function TABRAnovaForm.InitData(out AData: TABRAnovaData): Boolean; var - cellstring: string; + cellStr: string; + groupVal: Integer; i, j, k: integer; begin Result := false; @@ -398,83 +417,87 @@ begin end; NoSelected := CList.Items.Count; - MinA := 10000; - MaxA := -10000; - MinB := 10000; - MaxB := -10000; + MinA := MaxInt; + MaxA := -MaxInt; + MinB := MaxInt; + MaxB := -MaxInt; for i := 1 to NoCases do begin if not ValidValue(OS3MainFrm.DataGrid, i, ACol) then continue; - cellstring := Trim(OS3MainFrm.DataGrid.Cells[ACol,i]); - group := round(StrToFloat(cellstring)); - if (group > MaxA) then MaxA := group; - if (group < MinA) then MinA := group; + cellStr := Trim(OS3MainFrm.DataGrid.Cells[ACol, i]); + groupVal := round(StrToFloat(cellstr)); + if (groupVal > MaxA) then MaxA := groupVal; + if (groupVal < MinA) then MinA := groupVal; - cellstring := Trim(OS3MainFrm.DataGrid.Cells[BCol,i]); + cellStr := Trim(OS3MainFrm.DataGrid.Cells[BCol, i]); if not ValidValue(OS3MainFrm.DataGrid, i, BCol) then continue; - group := round(StrToFLoat(cellstring)); - if (group > MaxB) then MaxB := group; - if (group < MinB) then MinB := group; + groupVal := round(StrToFLoat(cellStr)); + if (groupVal > MaxB) then MaxB := groupVal; + if (groupVal < MinB) then MinB := groupVal; end; - NoAGrps := MaxA - MinA + 1; - NoBGrps := MaxB - MinB + 1; - MaxRows := NoAGrps * NoBGrps; - MaxCols := NoSelected; - if (NoBGrps > NoSelected) then MaxCols := NoBGrps; - if (MaxCols > MaxRows) then MaxRows := MaxCols; - // allocate storage for arrays - SetLength(ASums, NoAGrps); - SetLength(Bsums, NoBGrps); - SetLength(Csums, NoCases); - SetLength(ABSums, NoAGrps, NoBGrps); - SetLength(ACSums, NoAGrps, NoSelected); - SetLength(BCSums, NoBGrps, NoSelected); - SetLength(SumPSqr, NoCases); - SetLength(Acnt, NoAGrps); - SetLength(Bcnt, NoBGrps); - SetLength(Ccnt, MaxRows); - SetLength(ABCSums, NoAGrps, NoBGrps, NoSelected); - SetLength(ABCNcnt, NoAGrps, NoBGrps, NoSelected); - - // initialize arrays - for i := 0 to NoAGrps-1 do + with AData do begin - ASums[i] := 0.0; - Acnt[i] := 0; - for j := 0 to NoBGrps-1 do + NoAGrps := MaxA - MinA + 1; + NoBGrps := MaxB - MinB + 1; + MaxRows := NoAGrps * NoBGrps; + MaxCols := NoSelected; + if (NoBGrps > NoSelected) then MaxCols := NoBGrps; + if (MaxCols > MaxRows) then MaxRows := MaxCols; + + // allocate storage for arrays + SetLength(ASums, NoAGrps); + SetLength(Bsums, NoBGrps); + SetLength(Csums, NoCases); + SetLength(ABSums, NoAGrps, NoBGrps); + SetLength(ACSums, NoAGrps, NoSelected); + SetLength(BCSums, NoBGrps, NoSelected); + SetLength(SumPSqr, NoCases); + SetLength(Acnt, NoAGrps); + SetLength(Bcnt, NoBGrps); + SetLength(Ccnt, MaxRows); + SetLength(ABCSums, NoAGrps, NoBGrps, NoSelected); + SetLength(ABCNcnt, NoAGrps, NoBGrps, NoSelected); + + // initialize arrays + for i := 0 to NoAGrps-1 do begin - ABSums[i, j] := 0.0; - for k := 0 to NoSelected-1 do + ASums[i] := 0.0; + Acnt[i] := 0; + for j := 0 to NoBGrps-1 do begin - ABCSums[i, j, k] := 0.0; - ABCNcnt[i, j, k] := 0; + ABSums[i, j] := 0.0; + for k := 0 to NoSelected-1 do + begin + ABCSums[i, j, k] := 0.0; + ABCNcnt[i, j, k] := 0; + end; + end; + for j := 0 to NoSelected-1 do + begin + ACSums[i, j] := 0.0; end; end; - for j := 0 to NoSelected-1 do + for i := 0 to NoBGrps-1 do begin - ACSums[i, j] := 0.0; + BSums[i] := 0.0; + Bcnt[i] := 0; + for j := 0 to NoSelected-1 do + begin + BCSums[i, j] := 0.0; + end; end; - end; - for i := 0 to NoBGrps-1 do - begin - BSums[i] := 0.0; - Bcnt[i] := 0; - for j := 0 to NoSelected-1 do + for i := 0 to NoSelected-1 do begin - BCSums[i, j] := 0.0; + CSums[i] := 0.0; + Ccnt[i] := 0; end; + for i := 0 to NoCases-1 do + SumPSqr[i] := 0.0; + GrandTotal := 0.0; + TotalN := 0; + SumXSqr := 0.0; end; - for i := 0 to NoSelected-1 do - begin - CSums[i] := 0.0; - Ccnt[i] := 0; - end; - for i := 0 to NoCases-1 do - SumPSqr[i] := 0.0; - GrandTotal := 0.0; - TotalN := 0; - SumXSqr := 0.0; Result := true; end; @@ -501,10 +524,11 @@ begin end; -procedure TABRAnovaForm.GetData; +procedure TABRAnovaForm.GetData(var AData: TABRAnovaData); var i, j, SubjA, SubjB: integer; X: double; + subjTot: Double; begin for i := 0 to NoSelected - 1 do ColNoSelected[i] := GetVariableIndex(OS3MainFrm.DataGrid, CList.Items[i]); @@ -514,217 +538,228 @@ begin selected := NoSelected + 2; // read data and store sums - for i := 1 to NoCases do + with AData do begin - if not DataProcs.GoodRecord(i,selected,ColNoSelected) then continue; - SubjA := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ACol,i]))); - SubjA := SubjA - MinA + 1; - SubjB := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[BCol,i]))); - SubjB := SubjB - MinB + 1; - SubjTot := 0.0; - for j := 0 to NoSelected-1 do + for i := 1 to NoCases do begin - X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[j], i])); - SubjTot := SubjTot + X; - SumXSqr := SumXSqr + (X * X); - ABCSums[SubjA-1, SubjB-1, j] := ABCSums[SubjA-1, SubjB-1, j] + X; - ABCNcnt[SubjA-1, SubjB-1, j] := ABCNcnt[SubjA-1, SubjB-1, j] + 1; - Acnt[SubjA-1] := Acnt[SubjA-1] + 1; - Bcnt[SubjB-1] := Bcnt[SubjB-1] + 1; - Ccnt[j] := Ccnt[j] + 1; - TotalN := TotalN + 1; + if not DataProcs.GoodRecord(i,selected,ColNoSelected) then continue; + SubjA := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ACol,i]))); + SubjA := SubjA - MinA + 1; + SubjB := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[BCol,i]))); + SubjB := SubjB - MinB + 1; + SubjTot := 0.0; + for j := 0 to NoSelected-1 do + begin + X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[j], i])); + SubjTot := SubjTot + X; + SumXSqr := SumXSqr + (X * X); + ABCSums[SubjA-1, SubjB-1, j] := ABCSums[SubjA-1, SubjB-1, j] + X; + ABCNcnt[SubjA-1, SubjB-1, j] := ABCNcnt[SubjA-1, SubjB-1, j] + 1; + Acnt[SubjA-1] := Acnt[SubjA-1] + 1; + Bcnt[SubjB-1] := Bcnt[SubjB-1] + 1; + Ccnt[j] := Ccnt[j] + 1; + TotalN := TotalN + 1; + end; + SumPSqr[i-1] := SumPSqr[i-1] + (SubjTot * SubjTot); + GrandTotal := GrandTotal + SubjTot; + NinGrp := ABCNcnt[0,0,0]; end; - SumPSqr[i-1] := SumPSqr[i-1] + (SubjTot * SubjTot); - GrandTotal := GrandTotal + SubjTot; - NinGrp := ABCNcnt[0,0,0]; end; end; -procedure TABRAnovaForm.Calculate; +procedure TABRAnovaForm.Calculate(var AData: TABRAnovaData); var SumA, SumB, SumC, SumAB, SumAC, SumBC, SumABC : double; Term1, Term2, Term3, Term4, Term5, Term6, Term7, Term8, Term9, Term10 : double; i, j, k, CountA, CountB, CountC: integer; begin - Term1 := (GrandTotal * GrandTotal) / TotalN; - Term2 := SumXSqr; - - Term3 := 0.0; - countA := 0; - for i := 0 to NoAGrps-1 do + with AData do begin - SumA := 0.0; - countA := countA + Acnt[i]; - for j := 0 to NoBGrps-1 do - for k := 0 to NoSelected-1 do SumA := SumA + ABCSums[i, j, k]; - ASums[i] := ASums[i] + SumA; - Term3 := Term3 + sqr(SumA); - end; - Term3 := Term3 / (NInGrp * NoBGrps * NoSelected); + Term1 := (GrandTotal * GrandTotal) / TotalN; + Term2 := SumXSqr; - Term4 := 0; - countB := 0; - for j := 0 to NoBGrps-1 do - begin - SumB := 0.0; - CountB := CountB + Bcnt[j]; + Term3 := 0.0; + countA := 0; for i := 0 to NoAGrps-1 do - for k := 0 to NoSelected-1 do SumB := SumB + ABCSums[i, j, k]; - BSums[j] := BSums[j] + SumB; - Term4 := Term4 + sqr(SumB); - end; - Term4 := Term4 / (NInGrp * NoAGrps * NoSelected); + begin + SumA := 0.0; + countA := countA + Acnt[i]; + for j := 0 to NoBGrps-1 do + for k := 0 to NoSelected-1 do SumA := SumA + ABCSums[i, j, k]; + ASums[i] := ASums[i] + SumA; + Term3 := Term3 + sqr(SumA); + end; + Term3 := Term3 / (NInGrp * NoBGrps * NoSelected); - Term5 := 0.0; - countC := 0; - for k := 0 to NoSelected-1 do - begin - SumC := 0.0; - CountC := CountC + Ccnt[k]; - for i := 0 to NoAGrps-1 do - for j := 0 to NoBGrps-1 do SumC := SumC + ABCSums[i, j, k]; - CSums[k] := CSums[k] + SumC; - Term5 := Term5 + sqr(SumC); - end; - Term5 := Term5 / (NInGrp * NoAGrps * NoBGrps); - - Term6 := 0.0; - for i := 0 to NoAGrps-1 do - begin + Term4 := 0; + countB := 0; for j := 0 to NoBGrps-1 do begin - SumAB := 0.0; - //CountAB := CountAB + ABcnt^[i,j]; - for k := 0 to NoSelected-1 do SumAB := SumAB + ABCSums[i, j, k]; - ABSums[i, j] := ABSums[i, j] + SumAB; - Term6 := Term6 + sqr(SumAB); + SumB := 0.0; + CountB := CountB + Bcnt[j]; + for i := 0 to NoAGrps-1 do + for k := 0 to NoSelected-1 do SumB := SumB + ABCSums[i, j, k]; + BSums[j] := BSums[j] + SumB; + Term4 := Term4 + sqr(SumB); end; - end; - Term6 := Term6 / (NInGrp * NoSelected); + Term4 := Term4 / (NInGrp * NoAGrps * NoSelected); - Term7 := 0.0; - for i := 0 to NoAGrps-1 do - begin + Term5 := 0.0; + countC := 0; for k := 0 to NoSelected-1 do begin - SumAC := 0.0; - for j := 0 to NoBGrps-1 do SumAC := SumAC + ABCSums[i, j, k]; - ACSums[i, k] := ACSums[i, k] + SumAC; - Term7 := Term7 + sqr(SumAC); + SumC := 0.0; + CountC := CountC + Ccnt[k]; + for i := 0 to NoAGrps-1 do + for j := 0 to NoBGrps-1 do SumC := SumC + ABCSums[i, j, k]; + CSums[k] := CSums[k] + SumC; + Term5 := Term5 + sqr(SumC); end; - end; - Term7 := Term7 / (NInGrp * NoBGrps); + Term5 := Term5 / (NInGrp * NoAGrps * NoBGrps); - Term8 := 0.0; - for j := 0 to NoBGrps-1 do - begin - for k := 0 to NoSelected-1 do + Term6 := 0.0; + for i := 0 to NoAGrps-1 do begin - SumBC := 0.0; - for i := 0 to NoAGrps-1 do SumBC := SumBC + ABCSums[i, j, k]; - BCSums[j, k] := BCSums[j, k] + SumBC; - Term8 := Term8 + sqr(SumBC); + for j := 0 to NoBGrps-1 do + begin + SumAB := 0.0; + //CountAB := CountAB + ABcnt^[i,j]; + for k := 0 to NoSelected-1 do SumAB := SumAB + ABCSums[i, j, k]; + ABSums[i, j] := ABSums[i, j] + SumAB; + Term6 := Term6 + sqr(SumAB); + end; end; - end; - Term8 := Term8 / (NInGrp * NoAGrps); + Term6 := Term6 / (NInGrp * NoSelected); - Term9 := 0.0; - for i := 0 to NoAGrps-1 do - begin + Term7 := 0.0; + for i := 0 to NoAGrps-1 do + begin + for k := 0 to NoSelected-1 do + begin + SumAC := 0.0; + for j := 0 to NoBGrps-1 do SumAC := SumAC + ABCSums[i, j, k]; + ACSums[i, k] := ACSums[i, k] + SumAC; + Term7 := Term7 + sqr(SumAC); + end; + end; + Term7 := Term7 / (NInGrp * NoBGrps); + + Term8 := 0.0; for j := 0 to NoBGrps-1 do begin for k := 0 to NoSelected-1 do begin - SumABC := ABCSums[i, j, k]; - //CountABC := CountABC + ABCNcnt[i,j,k]; - Term9 := Term9 + sqr(SumABC); + SumBC := 0.0; + for i := 0 to NoAGrps-1 do SumBC := SumBC + ABCSums[i, j, k]; + BCSums[j, k] := BCSums[j, k] + SumBC; + Term8 := Term8 + sqr(SumBC); end; end; + Term8 := Term8 / (NInGrp * NoAGrps); + + Term9 := 0.0; + for i := 0 to NoAGrps-1 do + begin + for j := 0 to NoBGrps-1 do + begin + for k := 0 to NoSelected-1 do + begin + SumABC := ABCSums[i, j, k]; + //CountABC := CountABC + ABCNcnt[i,j,k]; + Term9 := Term9 + sqr(SumABC); + end; + end; + end; + Term9 := Term9 / NInGrp; + + Term10 := 0.0; + for i := 0 to NoCases-1 do Term10 := Term10 + SumPSqr[i]; + Term10 := Term10 / NoSelected; + + //Get DF, SS, MS, F and Probabilities + DFBetween := (NInGrp * NoAGrps * NoBGrps) - 1.0; + DFA := NoAGrps - 1.0; + DFB := NoBGrps - 1.0; + DFAB := (NoAGrps - 1.0) * (NoBGrps - 1.0); + DFerrorBetween := (NoAGrps * NoBGrps) * (NInGrp - 1.0); + DFWithin := (NInGrp * NoAGrps * NoBGrps) * (NoSelected - 1.0); + DFC := NoSelected - 1.0; + DFAC := (NoAGrps - 1.0) * (NoSelected - 1.0); + DFBC := (NoBGrps - 1.0) * (NoSelected - 1.0); + DFABC := (NoAGrps - 1.0) * (NoBGrps - 1.0) * (NoSelected - 1.0); + DFerrorWithin := NoAGrps * NoBGrps * (NInGrp - 1.0) * (NoSelected - 1.0); + + SSBetweenSubjects := Term10 - Term1; + SSA := Term3 - Term1; + SSB := Term4 - Term1; + SSAB := Term6 - Term3 - Term4 + Term1; + SSerrorBetween := Term10 - Term6; + SSWithinSubjects := Term2 - Term10; + SSC := Term5 - Term1; + SSAC := Term7 - Term3 - Term5 + Term1; + SSBC := Term8 - Term4 - Term5 + Term1; + SSABC := Term9 - Term6 - Term7 - Term8 + Term3 + Term4 + Term5 - Term1; + SSerrorWithin := Term2 - Term9 - Term10 + Term6; + + MSA := SSA / DFA; + MSB := SSB / DFB; + MSAB := SSAB / DFAB; + MSerrorBetween := SSerrorBetween / DFerrorBetween; + MSC := SSC / DFC; + MSAC := SSAC / DFAC; + MSBC := SSBC / DFBC; + MSABC := SSABC / DFABC; + MSerrorWithin := SSerrorWithin / DFerrorWithin; + + FA := MSA / MSerrorBetween; + FB := MSB / MSerrorBetween; + FAB := MSAB / MSerrorBetween; + FC := MSC / MSerrorWithin; + FAC := MSAC / MSerrorWithin; + FBC := MSBC / MSerrorWithin; + FABC := MSABC / MSerrorWithin; + + ProbA := ProbF(FA, DFA, DFerrorBetween); + ProbB := ProbF(FB, DFB, DFerrorBetween); + ProbAB := ProbF(FAB, DFAB, DFerrorBetween); + ProbC := ProbF(FC, DFC, DFerrorWithin); + ProbAC := ProbF(FAC, DFAC, DFerrorWithin); + ProbBC := ProbF(FBC, DFBC, DFerrorWithin); + ProbABC := ProbF(FABC, DFABC, DFerrorWithin); end; - Term9 := Term9 / NInGrp; - - Term10 := 0.0; - for i := 0 to NoCases-1 do Term10 := Term10 + SumPSqr[i]; - Term10 := Term10 / NoSelected; - - //Get DF, SS, MS, F and Probabilities - DFBetween := (NInGrp * NoAGrps * NoBGrps) - 1.0; - DFA := NoAGrps - 1.0; - DFB := NoBGrps - 1.0; - DFAB := (NoAGrps - 1.0) * (NoBGrps - 1.0); - DFerrorBetween := (NoAGrps * NoBGrps) * (NInGrp - 1.0); - DFWithin := (NInGrp * NoAGrps * NoBGrps) * (NoSelected - 1.0); - DFC := NoSelected - 1.0; - DFAC := (NoAGrps - 1.0) * (NoSelected - 1.0); - DFBC := (NoBGrps - 1.0) * (NoSelected - 1.0); - DFABC := (NoAGrps - 1.0) * (NoBGrps - 1.0) * (NoSelected - 1.0); - DFerrorWithin := NoAGrps * NoBGrps * (NInGrp - 1.0) * (NoSelected - 1.0); - - SSBetweenSubjects := Term10 - Term1; - SSA := Term3 - Term1; - SSB := Term4 - Term1; - SSAB := Term6 - Term3 - Term4 + Term1; - SSerrorBetween := Term10 - Term6; - SSWithinSubjects := Term2 - Term10; - SSC := Term5 - Term1; - SSAC := Term7 - Term3 - Term5 + Term1; - SSBC := Term8 - Term4 - Term5 + Term1; - SSABC := Term9 - Term6 - Term7 - Term8 + Term3 + Term4 + Term5 - Term1; - SSerrorWithin := Term2 - Term9 - Term10 + Term6; - - MSA := SSA / DFA; - MSB := SSB / DFB; - MSAB := SSAB / DFAB; - MSerrorBetween := SSerrorBetween / DFerrorBetween; - MSC := SSC / DFC; - MSAC := SSAC / DFAC; - MSBC := SSBC / DFBC; - MSABC := SSABC / DFABC; - MSerrorWithin := SSerrorWithin / DFerrorWithin; - - FA := MSA / MSerrorBetween; - FB := MSB / MSerrorBetween; - FAB := MSAB / MSerrorBetween; - FC := MSC / MSerrorWithin; - FAC := MSAC / MSerrorWithin; - FBC := MSBC / MSerrorWithin; - FABC := MSABC / MSerrorWithin; - - ProbA := ProbF(FA, DFA, DFerrorBetween); - ProbB := ProbF(FB, DFB, DFerrorBetween); - ProbAB := ProbF(FAB, DFAB, DFerrorBetween); - ProbC := ProbF(FC, DFC, DFerrorWithin); - ProbAC := ProbF(FAC, DFAC, DFerrorWithin); - ProbBC := ProbF(FBC, DFBC, DFerrorWithin); - ProbABC := ProbF(FABC, DFABC, DFerrorWithin); end; -procedure TABRAnovaForm.Summarize(AReport: TStrings); +procedure TABRAnovaForm.Summarize(const AData: TABRAnovaData; AReport: TStrings); begin - AReport.Add('SOURCE DF SS MS F PROB.'); - AReport.Add(''); - AReport.Add('Between Subjects %5.0f%10.3f',[DFBetween, SSBetweenSubjects]); - AReport.Add(' A Effects %5.0f%10.3f%10.3f%10.3f%10.3f', [DFA, SSA, MSA, FA, ProbA]); - AReport.Add(' B Effects %5.0f%10.3f%10.3f%10.3f%10.3f', [DFB, SSB, MSB, FB, ProbB]); - AReport.Add(' AB Effects %5.0f%10.3f%10.3f%10.3f%10.3f', [DFAB, SSAB, MSAB, FAB, ProbAB]); - AReport.Add(' Error Between %5.0f%10.3f%10.3f', [DFerrorBetween,SSerrorBetween,MSerrorBetween]); - AReport.Add(''); - AReport.Add('Within Subjects %5.0f%10.3f', [DFWithin, SSWithinSubjects]); - AReport.Add(' C Replications %5.0f%10.3f%10.3f%10.3f%10.3f', [DFC, SSC, MSC, FC, ProbC]); - AReport.Add(' AC Effects %5.0f%10.3f%10.3f%10.3f%10.3f', [DFAC, SSAC, MSAC, FAC, ProbAC]); - AReport.Add(' BC Effects %5.0f%10.3f%10.3f%10.3f%10.3f', [DFBC, SSBC, MSBC, FBC, ProbBC]); - AReport.Add(' ABC Effects %5.0f%10.3f%10.3f%10.3f%10.3f', [DFABC, SSABC, MSABC, FABC, ProbABC]); - AReport.Add(' Error Within %5.0f%10.3f%10.3f', [DFerrorWithin, SSerrorWithin, MSerrorWithin]); - AReport.Add(''); - AReport.Add('Total %5.0f%10.3f', [DFBetween + DFWithin, SSBetweenSubjects + SSWithinSubjects]); - AReport.Add(''); + with AData do + begin + AReport.Add(DIVIDER_SMALL_AUTO); + AReport.Add('SOURCE DF SS MS F PROB.'); + AReport.Add(DIVIDER_SMALL_AUTO); + AReport.Add('Between Subjects %5.0f%10.3f', [DFBetween, SSBetweenSubjects]); + AReport.Add(' A Effects %5.0f%10.3f%10.3f%10.3f%10.3f', [DFA, SSA, MSA, FA, ProbA]); + AReport.Add(' B Effects %5.0f%10.3f%10.3f%10.3f%10.3f', [DFB, SSB, MSB, FB, ProbB]); + AReport.Add(' AB Effects %5.0f%10.3f%10.3f%10.3f%10.3f', [DFAB, SSAB, MSAB, FAB, ProbAB]); + AReport.Add(' Error Between %5.0f%10.3f%10.3f', [DFerrorBetween, SSerrorBetween, MSerrorBetween]); + AReport.Add(''); + AReport.Add('Within Subjects %5.0f%10.3f', [DFWithin, SSWithinSubjects]); + AReport.Add(' C Replications %5.0f%10.3f%10.3f%10.3f%10.3f', [DFC, SSC, MSC, FC, ProbC]); + AReport.Add(' AC Effects %5.0f%10.3f%10.3f%10.3f%10.3f', [DFAC, SSAC, MSAC, FAC, ProbAC]); + AReport.Add(' BC Effects %5.0f%10.3f%10.3f%10.3f%10.3f', [DFBC, SSBC, MSBC, FBC, ProbBC]); + AReport.Add(' ABC Effects %5.0f%10.3f%10.3f%10.3f%10.3f', [DFABC, SSABC, MSABC, FABC, ProbABC]); + AReport.Add(' Error Within %5.0f%10.3f%10.3f', [DFerrorWithin, SSerrorWithin, MSerrorWithin]); + AReport.Add(''); +// AReport.Add(DIVIDER_SMALL_AUTO); + AReport.Add('Total %5.0f%10.3f', [DFBetween + DFWithin, SSBetweenSubjects + SSWithinSubjects]); + AReport.Add(DIVIDER_SMALL_AUTO); + end; FReportFrame.DisplayReport(AReport); AReport.Clear; end; -procedure TABRAnovaForm.MeansReport(AReport: TStrings); +procedure TABRAnovaForm.MeansReport(const AData: TABRAnovaData; AReport: TStrings); var ColLabels: StrDyneVec = nil; RowLabels: StrDyneVec = nil; @@ -742,80 +777,80 @@ begin SetLength(RowLabels, MaxRows); SetLength(ColLabels, NoSelected); row := 0; - for i := 0 to NoAGrps-1 do + for i := 0 to AData.NoAGrps-1 do begin - for j := 0 to NoBGrps-1 do + for j := 0 to AData.NoBGrps-1 do begin RowLabels[row] := Format('A%d B%d',[i+1, j+1]); for k := 0 to NoSelected-1 do begin - AMatrix[row, k] := ABCSums[i, j, k] / NInGrp; + AMatrix[row, k] := AData.ABCSums[i, j, k] / AData.NInGrp; ColLabels[k] := OS3MainFrm.DataGrid.Cells[ColNoSelected[k], 0]; end; inc(row); end; end; - MatPrint(AMatrix, MaxRows, NoSelected, Title, RowLabels, ColLabels, NInGrp, AReport); + MatPrint(AMatrix, MaxRows, NoSelected, Title, RowLabels, ColLabels, AData.NInGrp, AReport); AReport.Add(DIVIDER_SMALL_AUTO); AReport.Add(''); Title := 'AB Means Table'; ColHeader := 'B Levels'; - SetLength(AMatrix, NoAGrps, NoBGrps); - SetLength(RowLabels, NoAGrps); - SetLength(ColLabels, NoBGrps); - for i := 0 to NoAGrps-1 do + SetLength(AMatrix, AData.NoAGrps, AData.NoBGrps); + SetLength(RowLabels, AData.NoAGrps); + SetLength(ColLabels, AData.NoBGrps); + for i := 0 to AData.NoAGrps-1 do begin RowLabels[i] := Format('A%d',[i+1]); - for j := 0 to NoBGrps-1 do - AMatrix[i, j] := ABSums[i, j] / (NInGrp * NoSelected); + for j := 0 to AData.NoBGrps-1 do + AMatrix[i, j] := AData.ABSums[i, j] / (AData.NInGrp * NoSelected); end; - for j := 0 to NoBGrps-1 do + for j := 0 to AData.NoBGrps-1 do ColLabels[j] := Format('B %d',[j+1]); - MatPrint(AMatrix, NoAgrps, NoBgrps, Title, RowLabels, ColLabels, NinGrp*NoSelected, AReport); + MatPrint(AMatrix, AData.NoAgrps, AData.NoBgrps, Title, RowLabels, ColLabels, AData.NinGrp*NoSelected, AReport); AReport.Add(DIVIDER_SMALL_AUTO); AReport.Add(''); Title := 'AC Means Table'; ColHeader := 'C Levels'; - SetLength(AMatrix, NoAGrps, NoSelected); - SetLength(RowLabels, NoAGrps); + SetLength(AMatrix, AData.NoAGrps, NoSelected); + SetLength(RowLabels, AData.NoAGrps); SetLength(ColLabels, NoSelected); - for i := 0 to NoAGrps-1 do + for i := 0 to AData.NoAGrps-1 do begin RowLabels[i] := Format('A%d',[i+1]); for j := 0 to NoSelected-1 do - AMatrix[i, j] := ACSums[i, j] / (NInGrp * NoBGrps); + AMatrix[i, j] := AData.ACSums[i, j] / (AData.NInGrp * AData.NoBGrps); end; for j := 0 to NoSelected-1 do ColLabels[j] := Format('C%d',[j+1]); - MatPrint(AMatrix, NoAGrps, NoSelected, Title, RowLabels, ColLabels, NInGrp*NoBGrps, AReport); + MatPrint(AMatrix, AData.NoAGrps, NoSelected, Title, RowLabels, ColLabels, AData.NInGrp*AData.NoBGrps, AReport); AReport.Add(DIVIDER_SMALL_AUTO); AReport.Add(''); Title := 'BC Means Table'; ColHeader := 'C Levels'; - SetLength(AMatrix, NoBGrps, NoSelected); - SetLength(RowLabels, NoBGrps); + SetLength(AMatrix, AData.NoBGrps, NoSelected); + SetLength(RowLabels, AData.NoBGrps); SetLength(ColLabels, NoSelected); - for i := 0 to NoBGrps-1 do + for i := 0 to AData.NoBGrps-1 do begin RowLabels[i] := Format('B%d',[i+1]); for j := 0 to NoSelected-1 do - AMatrix[i, j] := BCSums[i, j] / (NInGrp * NoAGrps); + AMatrix[i, j] := AData.BCSums[i, j] / (AData.NInGrp * AData.NoAGrps); end; for j := 0 to NoSelected-1 do ColLabels[j] := Format('C%d', [j+1]); - MatPrint(AMatrix, NoBGrps, NoSelected, Title, RowLabels, ColLabels, NInGrp*NoAGrps, AReport); + MatPrint(AMatrix, AData.NoBGrps, NoSelected, Title, RowLabels, ColLabels, AData.NInGrp*AData.NoAGrps, AReport); FMeansReportFrame.DisplayReport(AReport); AReport.Clear; end; -procedure TABRAnovaForm.BoxTests(AReport: TStrings); +procedure TABRAnovaForm.BoxTests(const AData: TABRAnovaData; AReport: TStrings); const EPS = 1E-35; var @@ -855,9 +890,9 @@ begin // covariance AMatrix. Get Determinants of each AMatrix. //OutputFrm.Clear; Sum1 := 0.0; - for i := 1 to NoAGrps do + for i := 1 to AData.NoAGrps do begin - for j := 1 to NoBGrps do + for j := 1 to AData.NoBGrps do begin LabelStr := Format('Variance-Covariance AMatrix for A%d B%d', [i,j]); Title := LabelStr; @@ -899,8 +934,8 @@ begin begin for L := 0 to NoSelected-1 do begin - AMatrix[k, L] := AMatrix[k, L] - (XSums[k]*XSums[L] / NInGrp); - AMatrix[k, L] := AMatrix[k, L] / (NInGrp - 1); + AMatrix[k, L] := AMatrix[k, L] - (XSums[k]*XSums[L] / AData.NInGrp); + AMatrix[k, L] := AMatrix[k, L] / (AData.NInGrp - 1); PooledMat[k, L] := PooledMat[k, L] + AMatrix[k, L]; end; end; @@ -916,7 +951,7 @@ begin Determ(DetMat, NoSelected, NoSelected, Det, errorcode); // if (Det > 0.0e35) then // wp: What's this??? if Det > EPS then - Sum1 := sum1 + (NinGrp * ln(Det)) + Sum1 := sum1 + (AData.NInGrp * ln(Det)) else MessageDlg('Determinant of a covariance AMatrix <= 0.', mtWarning, [mbOK], 0); end;// next B level @@ -925,7 +960,7 @@ begin // Get pooled variance-covariance for i := 0 to NoSelected-1 do for j := 0 to NoSelected-1 do - PooledMat[i, j] := PooledMat[i, j] / (NoAGrps * NoBGrps); + PooledMat[i, j] := PooledMat[i, j] / (AData.NoAGrps * AData.NoBGrps); Title := 'Pooled Variance-Covariance AMatrix'; MatPrint(PooledMat, NoSelected, NoSelected, Title, RowLabels, ColLabels, NoCases, AReport); @@ -942,11 +977,14 @@ begin Determ(DetMat, NoSelected, NoSelected, Det, errorcode); if (Det > EPS) then begin - M1 := (NinGrp*NoAGrps*NoBGrps * ln(Det)) - Sum1; - C1 := (2.0 * NoSelected * NoSelected + 3.0 * NoSelected - 1.0) / - (6.0 * (NoSelected+1) * (NoAGrps * NoBGrps - 1.0)); - C1 := C1 * ( (NoAGrps * NoBGrps * (1.0 / NinGrp)) - (1.0 / (NinGrp * NoAGrps * NoBGrps))); - f1 := (NoSelected * (NoSelected + 1.0) * (NoAGrps * NoBGrps - 1.0))/2.0; + with AData do + begin + M1 := (NinGrp*NoAGrps*NoBGrps * ln(Det)) - Sum1; + C1 := (2.0 * NoSelected * NoSelected + 3.0 * NoSelected - 1.0) / + (6.0 * (NoSelected+1) * (NoAGrps * NoBGrps - 1.0)); + C1 := C1 * ( (NoAGrps * NoBGrps * (1.0 / NinGrp)) - (1.0 / (NinGrp * NoAGrps * NoBGrps))); + f1 := (NoSelected * (NoSelected + 1.0) * (NoAGrps * NoBGrps - 1.0))/2.0; + end; chi := (1.0 - C1) * M1; ProbChi := 1.0 - ChiSquaredProb(chi, round(f1)); AReport.Add('Test that sample covariances are from same population:'); @@ -986,8 +1024,11 @@ begin Determ(DetMat, NoSelected, NoSelected, Det, errorcode); if (Det > EPS) then begin - N := NoAGrps * NoBGrps * NinGrp; - p := NoAGrps * NoBGrps; + with AData do + begin + N := NoAGrps * NoBGrps * NinGrp; + p := NoAGrps * NoBGrps; + end; quad := NoSelected * NoSelected + NoSelected - 4; M2 := ln(M2 / Det); M2 := -(N - p) * M2; @@ -1009,59 +1050,6 @@ begin end; -procedure TABRAnovaForm.PreparePlot; -var - idx: Integer; - item: PChartDataItem; - i, j: Integer; -begin - FChartFrame.Clear; - ListChartSource_AB.Clear; - ListChartSource_AC.Clear; - ListChartSource_BC.Clear; - ChartStyles.Styles.Clear; - - ListChartSource_AB.YCount := NoAGrps; - for j := 0 to NoBGrps-1 do - begin - idx := ListChartSource_AB.Add(j+1, 0); - item := ListChartSource_AB.Item[idx]; - for i := 0 to NoAGrps-1 do - item^.SetY(i, ABSums[i, j] / (NInGrp * NoSelected)); - end; - - ListChartSource_AC.YCount := NoAGrps; - for j := 0 to NoSelected-1 do - begin - idx := ListChartSource_AC.Add(j+1, 0); - item := ListChartSource_AC.Item[idx]; - for i := 0 to NoAGrps-1 do - item^.SetY(i, ACSums[i, j] / (NInGrp * NoBGrps)); - end; - - ListChartSource_BC.YCount := NoBGrps; - for j := 0 to NoSelected-1 do - begin - idx := ListChartSource_BC.Add(j+1, 0); - item := ListChartSource_BC.Item[idx]; - for i := 0 to NoBGrps-1 do - item^.SetY(i, BCSums[i, j] / (NInGrp * NoAGrps)); - end; - - FBarSeries := FChartFrame.PlotXY(ptBars, nil, nil, nil, nil, '', clDefault) as TBarSeries; - with FBarSeries do - begin - Legend.Multiplicity := lmStyle; - Stacked := false; - Styles := ChartStyles; - {$IF LCL_FullVersion >= 2010000} - DepthBrightnessDelta := -30; - {$IFEND} - end; - -end; - - procedure TABRAnovaForm.PlotMeans(AInteraction: TInteraction); const X_TITLE: array[TInteraction] of string = ( @@ -1085,6 +1073,7 @@ begin end; FBarSeries.Source := serSource; + Set3DPlot(ThreeDChk.Checked); ChartStyles.Styles.Clear; for i := 0 to serSource.YCount-1 do @@ -1105,6 +1094,58 @@ begin end; +procedure TABRAnovaForm.PreparePlot(const AData: TABRAnovaData); +var + idx: Integer; + item: PChartDataItem; + i, j: Integer; +begin + FChartFrame.Clear; + ListChartSource_AB.Clear; + ListChartSource_AC.Clear; + ListChartSource_BC.Clear; + ChartStyles.Styles.Clear; + + ListChartSource_AB.YCount := AData.NoAGrps; + for j := 0 to AData.NoBGrps-1 do + begin + idx := ListChartSource_AB.Add(j+1, 0); + item := ListChartSource_AB.Item[idx]; + for i := 0 to AData.NoAGrps-1 do + item^.SetY(i, AData.ABSums[i, j] / (AData.NInGrp * NoSelected)); + end; + + ListChartSource_AC.YCount := AData.NoAGrps; + for j := 0 to NoSelected-1 do + begin + idx := ListChartSource_AC.Add(j+1, 0); + item := ListChartSource_AC.Item[idx]; + for i := 0 to AData.NoAGrps-1 do + item^.SetY(i, AData.ACSums[i, j] / (AData.NInGrp * AData.NoBGrps)); + end; + + ListChartSource_BC.YCount := AData.NoBGrps; + for j := 0 to NoSelected-1 do + begin + idx := ListChartSource_BC.Add(j+1, 0); + item := ListChartSource_BC.Item[idx]; + for i := 0 to AData.NoBGrps-1 do + item^.SetY(i, AData.BCSums[i, j] / (AData.NInGrp * AData.NoAGrps)); + end; + + FBarSeries := FChartFrame.PlotXY(ptBars, nil, nil, nil, nil, '', clDefault) as TBarSeries; + with FBarSeries do + begin + Legend.Multiplicity := lmStyle; + Stacked := false; + Styles := ChartStyles; + {$IF LCL_FullVersion >= 2010000} + DepthBrightnessDelta := -30; + {$IFEND} + end; +end; + + procedure TABRAnovaForm.Reset; var i: integer; @@ -1131,6 +1172,24 @@ begin end; +procedure TABRAnovaForm.Set3DPlot(AEnable: Boolean); +const + DEPTH: array[boolean] of Integer = (0, 20); +begin + if (FBarSeries <> nil) then + begin + FBarSeries.Depth := DEPTH[AEnable]; + FChartFrame.Chart.LeftAxis.Grid.Visible := not AEnable; + end; +end; + + +procedure TABRAnovaForm.ThreeDChkChange(Sender: TObject); +begin + Set3DPlot(ThreeDChk.Checked); +end; + + procedure TABRAnovaForm.UpdateBtnStates; var lSelected: Boolean;