diff --git a/applications/lazstats/source/LazStats.lpi b/applications/lazstats/source/LazStats.lpi index eaeaef4b8..ce5dc0337 100644 --- a/applications/lazstats/source/LazStats.lpi +++ b/applications/lazstats/source/LazStats.lpi @@ -84,6 +84,11 @@ + + + + + @@ -1576,6 +1581,11 @@ + + + + + diff --git a/applications/lazstats/source/forms/analysis/comparisons/onecaseanovaunit.lfm b/applications/lazstats/source/forms/analysis/comparisons/onecaseanovaunit.lfm index 8c54a8c75..20d967ac2 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/onecaseanovaunit.lfm +++ b/applications/lazstats/source/forms/analysis/comparisons/onecaseanovaunit.lfm @@ -10,35 +10,35 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm ClientWidth = 940 inherited ParamsPanel: TPanel Height = 529 - Width = 313 + Width = 419 ClientHeight = 529 - ClientWidth = 313 + ClientWidth = 419 inherited CloseBtn: TButton - Left = 258 + Left = 364 Top = 504 end inherited ComputeBtn: TButton - Left = 174 + Left = 280 Top = 504 end inherited ResetBtn: TButton - Left = 112 + Left = 218 Top = 504 end inherited HelpBtn: TButton Tag = 107 - Left = 53 + Left = 159 Top = 504 end inherited ButtonBevel: TBevel Top = 488 - Width = 313 + Width = 419 end object Label3: TLabel[5] - AnchorSideTop.Control = OverAllAlphaEdit + AnchorSideTop.Control = OverallAlphaEdit AnchorSideTop.Side = asrCenter - AnchorSideRight.Control = OverAllAlphaEdit - Left = 175 + AnchorSideRight.Control = OverallAlphaEdit + Left = 281 Height = 30 Top = 297 Width = 79 @@ -49,14 +49,14 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm Caption = 'Alpha Level for'#13#10'Overall Tests' ParentColor = False end - object OverAllAlphaEdit: TEdit[6] + object OverallAlphaEdit: TEdit[6] AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = Factor3Edit AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Factor3Edit AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = ButtonBevel - Left = 262 + Left = 368 Height = 23 Top = 301 Width = 51 @@ -64,14 +64,14 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm Anchors = [akTop, akRight] BorderSpacing.Top = 24 TabOrder = 4 - Text = 'OverAllAlphaEdit' + Text = 'OverallAlphaEdit' end object Label4: TLabel[7] AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = PostAlphaEdit AnchorSideTop.Side = asrCenter AnchorSideRight.Control = PostAlphaEdit - Left = 74 + Left = 58 Height = 15 Top = 469 Width = 163 @@ -87,7 +87,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideRight.Control = PostHocGroup AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = ButtonBevel - Left = 245 + Left = 229 Height = 23 Top = 465 Width = 51 @@ -99,11 +99,10 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm end object PostHocGroup: TGroupBox[9] AnchorSideLeft.Control = ParamsPanel - AnchorSideLeft.Side = asrCenter AnchorSideTop.Side = asrBottom AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = PostAlphaEdit - Left = 16 + Left = 0 Height = 93 Top = 364 Width = 280 @@ -166,11 +165,11 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm end end object InteractChk: TCheckBox[10] - AnchorSideTop.Control = OverAllAlphaEdit + AnchorSideTop.Control = OverallAlphaEdit AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = OverAllAlphaEdit + AnchorSideRight.Control = OverallAlphaEdit AnchorSideRight.Side = asrBottom - Left = 210 + Left = 316 Height = 19 Top = 332 Width = 103 @@ -201,7 +200,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm Left = 0 Height = 331 Top = 17 - Width = 137 + Width = 190 Anchors = [akTop, akLeft, akRight, akBottom] BorderSpacing.Top = 2 BorderSpacing.Right = 6 @@ -214,7 +213,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideLeft.Control = ParamsPanel AnchorSideLeft.Side = asrCenter AnchorSideTop.Control = VarList - Left = 143 + Left = 196 Height = 26 Top = 17 Width = 26 @@ -228,7 +227,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideLeft.Control = DepIn AnchorSideTop.Control = DepIn AnchorSideTop.Side = asrBottom - Left = 143 + Left = 196 Height = 26 Top = 47 Width = 26 @@ -243,7 +242,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideLeft.Control = DepIn AnchorSideTop.Control = DepOut AnchorSideTop.Side = asrBottom - Left = 143 + Left = 196 Height = 26 Top = 89 Width = 26 @@ -258,7 +257,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideLeft.Control = DepIn AnchorSideTop.Control = Fact1In AnchorSideTop.Side = asrBottom - Left = 143 + Left = 196 Height = 26 Top = 119 Width = 26 @@ -273,7 +272,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideLeft.Control = DepIn AnchorSideTop.Control = Fact1Out AnchorSideTop.Side = asrBottom - Left = 143 + Left = 196 Height = 26 Top = 161 Width = 26 @@ -288,7 +287,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideLeft.Control = DepIn AnchorSideTop.Control = Fact2In AnchorSideTop.Side = asrBottom - Left = 143 + Left = 196 Height = 26 Top = 191 Width = 26 @@ -303,7 +302,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideLeft.Control = DepIn AnchorSideTop.Control = Fact2Out AnchorSideTop.Side = asrBottom - Left = 143 + Left = 196 Height = 26 Top = 233 Width = 26 @@ -318,7 +317,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideLeft.Control = DepIn AnchorSideTop.Control = Fact3In AnchorSideTop.Side = asrBottom - Left = 143 + Left = 196 Height = 26 Top = 263 Width = 26 @@ -333,7 +332,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideLeft.Control = DepIn AnchorSideLeft.Side = asrBottom AnchorSideBottom.Control = DepVarEdit - Left = 177 + Left = 230 Height = 16 Top = 20 Width = 103 @@ -351,10 +350,10 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = DepOut AnchorSideBottom.Side = asrBottom - Left = 177 + Left = 230 Height = 23 Top = 38 - Width = 136 + Width = 189 Anchors = [akLeft, akRight, akBottom] BorderSpacing.Left = 8 BorderSpacing.Bottom = 12 @@ -366,7 +365,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideLeft.Control = DepIn AnchorSideLeft.Side = asrBottom AnchorSideBottom.Control = Factor1Edit - Left = 177 + Left = 230 Height = 16 Top = 92 Width = 87 @@ -384,10 +383,10 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = Fact1Out AnchorSideBottom.Side = asrBottom - Left = 177 + Left = 230 Height = 23 Top = 110 - Width = 136 + Width = 189 Anchors = [akLeft, akRight, akBottom] BorderSpacing.Left = 8 BorderSpacing.Bottom = 12 @@ -399,7 +398,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideLeft.Control = DepIn AnchorSideLeft.Side = asrBottom AnchorSideBottom.Control = Factor2Edit - Left = 177 + Left = 230 Height = 16 Top = 164 Width = 87 @@ -417,10 +416,10 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = Fact2Out AnchorSideBottom.Side = asrBottom - Left = 177 + Left = 230 Height = 23 Top = 182 - Width = 136 + Width = 189 Anchors = [akLeft, akRight, akBottom] BorderSpacing.Left = 8 BorderSpacing.Bottom = 12 @@ -432,7 +431,7 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideLeft.Control = DepIn AnchorSideLeft.Side = asrBottom AnchorSideBottom.Control = Factor3Edit - Left = 177 + Left = 230 Height = 16 Top = 236 Width = 72 @@ -450,10 +449,10 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = Fact3Out AnchorSideBottom.Side = asrBottom - Left = 177 + Left = 230 Height = 23 Top = 254 - Width = 136 + Width = 189 Anchors = [akLeft, akRight, akBottom] BorderSpacing.Left = 8 BorderSpacing.Bottom = 12 @@ -461,14 +460,74 @@ inherited OneCaseAnovaForm: TOneCaseAnovaForm TabOrder = 24 Text = 'Factor3Edit' end + object PlotGroup: TGroupBox[29] + AnchorSideLeft.Control = PostHocGroup + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = PostHocGroup + AnchorSideBottom.Control = PostHocGroup + AnchorSideBottom.Side = asrBottom + Left = 296 + Height = 78 + Top = 364 + Width = 95 + AutoSize = True + BorderSpacing.Left = 16 + Caption = 'Plots' + ClientHeight = 58 + ClientWidth = 91 + TabOrder = 25 + object ShowPlotsChk: TCheckBox + AnchorSideLeft.Control = PlotGroup + AnchorSideTop.Control = PlotGroup + Left = 12 + Height = 19 + Top = 8 + Width = 79 + BorderSpacing.Left = 12 + BorderSpacing.Top = 8 + Caption = 'Plot Means' + Checked = True + OnChange = ShowPlotsChkChange + State = cbChecked + TabOrder = 0 + end + object Plot3DChk: TCheckBox + AnchorSideLeft.Control = ShowPlotsChk + AnchorSideTop.Control = ShowPlotsChk + AnchorSideTop.Side = asrBottom + Left = 36 + Height = 19 + Top = 27 + Width = 34 + BorderSpacing.Left = 24 + BorderSpacing.Right = 12 + BorderSpacing.Bottom = 12 + Caption = '3D' + OnChange = Plot3DChkChange + TabOrder = 1 + end + end end inherited ParamsSplitter: TSplitter - Left = 325 + Left = 431 Height = 545 end inherited PageControl: TPageControl - Left = 334 + Left = 440 Height = 529 - Width = 598 + Width = 492 + ActivePage = ReportPage + TabIndex = 0 + inherited ReportPage: TTabSheet + Caption = 'ANOVA Results' + end + inherited ChartPage: TTabSheet + Caption = 'Plots' + TabVisible = False + end + object PostHocPage: TTabSheet[2] + Caption = 'Post-Hoc' + TabVisible = False + end end end diff --git a/applications/lazstats/source/forms/analysis/comparisons/onecaseanovaunit.pas b/applications/lazstats/source/forms/analysis/comparisons/onecaseanovaunit.pas index 529e59cc4..9b27eb415 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/onecaseanovaunit.pas +++ b/applications/lazstats/source/forms/analysis/comparisons/onecaseanovaunit.pas @@ -1,14 +1,15 @@ unit OneCaseANOVAUnit; {$mode objfpc}{$H+} +{$WARN 6058 off : Call to subroutine "$1" marked as inline is not inlined} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, - StdCtrls, Buttons, ExtCtrls, ComCtrls, + StdCtrls, Buttons, ExtCtrls, ComCtrls, LCLVersion, TASources, TACustomSeries, TAStyles, - MainUnit, Globals, DataProcs, GraphLib, + MainUnit, Globals, ReportFrameUnit, ANOVATestsUnit, BasicStatsReportAndChartFormUnit; type @@ -16,6 +17,8 @@ type { TOneCaseAnovaForm } TOneCaseAnovaForm = class(TBasicStatsReportAndChartForm) + ShowPlotsChk: TCheckBox; + Plot3DChk: TCheckBox; DepIn: TBitBtn; DepOut: TBitBtn; DepVarEdit: TEdit; @@ -28,19 +31,21 @@ type Factor1Edit: TEdit; Factor2Edit: TEdit; Factor3Edit: TEdit; + PlotGroup: TGroupBox; PostHocGroup: TGroupBox; InteractChk: TCheckBox; Label1: TLabel; Label3: TLabel; Label4: TLabel; NewmanKeulsChk: TCheckBox; - OverAllAlphaEdit: TEdit; + OverallAlphaEdit: TEdit; PostAlphaEdit: TEdit; ScheffeChk: TCheckBox; StaticText1: TStaticText; StaticText2: TStaticText; StaticText3: TStaticText; StaticText4: TStaticText; + PostHocPage: TTabSheet; TukeyBChk: TCheckBox; TukeyHSDChk: TCheckBox; TukeyKramerChk: TCheckBox; @@ -53,6 +58,8 @@ type procedure Fact2OutClick(Sender: TObject); procedure Fact3InClick(Sender: TObject); procedure Fact3OutClick(Sender: TObject); + procedure Plot3DChkChange(Sender: TObject); + procedure ShowPlotsChkChange(Sender: TObject); procedure VarListDblClick(Sender: TObject); procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean); @@ -60,22 +67,19 @@ type { private declarations } N: integer; ColNoSelected: IntDyneVec; - Nf1cells, Nf2cells, Nf3cells, TotalCells: integer; + Nf1cells, Nf2cells, Nf3cells: Integer; minf1, maxf1, minf2, maxf2, minf3, maxf3, nofactors: integer; NoGrpsA, NoGrpsB, NoGrpsC: integer; - SSDep, SSErr, SSF1, SSF2, SSF3, SSF1F2, SSF1F3, SSF2F3, SSF1F2F3: double; + SSDep, SSErr, SSF1, SSF2, SSF3, SSF1F2, SSF1F3, SSF2F3: double; MSDep, MSErr, MSF1, MSF2, MSF3, MSF1F2, MSF1F3, MSF2F3: double; DFTot, DFErr, DFF1, DFF2, DFF3, DFF1F2, DFF1F3, DFF2F3: double; Omega, OmegaF1, OmegaF2, OmegaF3, OmegaF1F2: double; OmegaF1F3, OmegaF2F3: double; FF1, FF2, FF1F2, ProbF1, ProbF2, ProbF3, ProbF1F2, ProbF1F3: double; FF3, FF2F3, FF1F3, ProbF2F3: double; - MeanDep, MeanF1, MeanF2, MeanF3: double; + MeanDep: Double; SSNonAdd, SSBalance,MSNonAdd, MSBalance, GrandMean, DFBalance: double; FNonAdd, ProbNonAdd: double; - cellcnts : IntDyneVec; // array of cell counts - cellvars : DblDyneVec; // arrray of cell sums of squares then variances - cellsums : DblDyneVec; // array of cell sums then means counts : IntDyneMat; // matrix for 2-way containing cell sizes sums : DblDyneMat; // matrix for 2-way containing cell sums vars : DblDyneMat; // matrix for 2-way containing sums of squares @@ -85,30 +89,26 @@ type ColCount : IntDyneVec; // 2 way col count SlcSums : DblDyneVec; // 3 way slice sums SlcCount : IntDyneVec; // 3 way slice counts - OrdMeansA, OrdMeansB, OrdMeansC : DblDyneVec; // reordered means for f1, f2, f3 - DepValues: DblDyneVec; - F1Values, F2Values, F3Values: DblDyneVec; // ToDo: Make them a StrDyneVec -// F1Labels, F2Labels, F3Labels: StrDyneVec; - OverAll, PostHocAlpha : double; // alphas for tests +// DepValues: DblDyneVec; wsum, wx2: DblDyneCube; ncnt : IntDyneCube; - CompError : boolean; equal_grp : boolean; // check for equal groups for post-hoc tests - comparisons : boolean; -// interacts : boolean; // true if 2 way interactions to be included in 3 way design procedure Init; - procedure GetLevels; - function Calc2Way: Boolean; - procedure TwoWayTable(AReport: TStrings); - procedure TwoWayContrasts(AReport: TStrings); + procedure GetLevels(out DepValues, F1Values, F2Values, F3Values: DblDyneVec); + procedure Init2Way; + function Calc2Way(const DepValues, F1Values, F2Values: DblDyneVec): Boolean; + procedure TwoWayTable; + procedure TwoWayContrasts; procedure TwoWayPlot; - function Calc3Way: Boolean; - procedure ThreeWayTable(AReport: TStrings); - procedure ThreeWayContrasts(AReport: TStrings); + procedure Init3Way; + function Calc3Way(const DepValues, F1Values, F2Values, F3Values: DblDyneVec): Boolean; + procedure ThreeWayTable; + procedure ThreeWayContrasts; procedure ThreeWayPlot; private + FPosthocReportFrame: TReportFrame; FSeries: TChartSeries; FChartCombobox: TCombobox; FStyles: TChartStyles; @@ -149,13 +149,16 @@ var lbl: TLabel; begin inherited; - - if GraphFrm = nil then - Application.CreateForm(TGraphFrm, GraphFrm); - OverAllAlphaEdit.Text := FormatFloat('0.00', DEFAULT_ALPHA_LEVEL); + OverallAlphaEdit.Text := FormatFloat('0.00', DEFAULT_ALPHA_LEVEL); PostAlphaEdit.Text := FormatFloat('0.00', DEFAULT_ALPHA_LEVEL); + FPosthocReportFrame := TReportFrame.Create(PostHocPage); + FPosthocReportFrame.Parent := PostHocPage; + FPosthocReportFrame.Align := alClient; + InitToolbar(FPosthocReportFrame.ReportToolbar, tpTop); + PostHocPage.PageIndex := 1; + FStyles := TChartStyles.Create(FChartFrame); panel := TPanel.Create(FChartFrame.ChartToolbar); @@ -180,6 +183,10 @@ begin panel.AutoSize := true; panel.BevelInner := bvNone; panel.BevelOuter := bvNone; + + FChartFrame.Chart.Margins.Bottom := 0; + + PageControl.ActivePageIndex := 0; end; @@ -192,7 +199,7 @@ begin PostAlphaEdit.Height + ButtonBevel.Height + CloseBtn.BorderSpacing.Top + CloseBtn.Height; ParamsPanel.Constraints.MinWidth := Max( 4*CloseBtn.Width + 3*CloseBtn.BorderSpacing.Left, - PostHocGroup.Width + PostHocGroup.Width + PlotGroup.BorderSpacing.Left + PlotGroup.Width ); FChartFrame.ChartToolbar.ButtonHeight := Max( @@ -239,6 +246,7 @@ begin UpdateBtnStates; end; + procedure TOneCaseAnovaForm.DepOutClick(Sender: TObject); begin if DepVarEdit.Text <> '' then @@ -249,6 +257,7 @@ begin UpdateBtnStates; end; + procedure TOneCaseAnovaForm.Fact1InClick(Sender: TObject); var index: integer; @@ -262,6 +271,7 @@ begin UpdateBtnStates; end; + procedure TOneCaseAnovaForm.Fact1OutClick(Sender: TObject); begin if Factor1Edit.Text <> '' then @@ -272,6 +282,7 @@ begin UpdateBtnStates; end; + procedure TOneCaseAnovaForm.Fact2InClick(Sender: TObject); var index: integer; @@ -285,6 +296,7 @@ begin UpdateBtnStates; end; + procedure TOneCaseAnovaForm.Fact2OutClick(Sender: TObject); begin if Factor2Edit.Text <> '' then @@ -295,6 +307,7 @@ begin UpdateBtnStates; end; + procedure TOneCaseAnovaForm.Fact3InClick(Sender: TObject); var index: integer; @@ -308,6 +321,7 @@ begin UpdateBtnStates; end; + procedure TOneCaseAnovaForm.Fact3OutClick(Sender: TObject); begin if Factor3Edit.Text <> '' then @@ -321,119 +335,46 @@ end; procedure TOneCaseAnovaForm.Compute; var - lReport: TStrings; - msg: String; - C: TWinControl; + DepValues, F1Values, F2Values, F3Values: DblDyneVec; +begin + // Initialize variables + Init; + + // Get min and max of each factor code + GetLevels(DepValues, F1Values, F2Values, F3Values); + + // Analysis + case NoFactors of + 2 : begin // Two-way anova + Init2Way; + if Calc2Way(DepValues, F1Values, F2Values) then + begin + TwoWayTable; + TwoWayContrasts; + TwoWayPlot; + end; + end; + + 3 : begin // Three way anova + Init3Way; + if Calc3Way(DepValues, F1Values, F2Values, F3Values) then + begin + ThreeWayTable; + ThreeWayContrasts; + ThreeWayPlot; + end; + end; + end; +end; + + +procedure TOneCaseAnovaForm.Init; begin if Factor3Edit.Text = '' then NoFactors := 2 else NoFactors := 3; - // initialize values - Init; - - // get min and max of each factor code - GetLevels; - - // Analysis - case NoFactors of - 2 : begin // two-way anova - SetLength(counts, Nf1cells, Nf2cells); // matrix for 2-way containing cell sizes - SetLength(sums, Nf1cells, Nf2cells); // matrix for 2-way containing cell sums - SetLength(vars, Nf1cells, Nf2cells); // matrix for 2-way containing sums of squares - SetLength(RowSums, Nf1cells); // 2 way row sums - SetLength(ColSums, Nf2cells); // 2 way col sums - SetLength(RowCount, Nf1cells); // 2 way row count - SetLength(ColCount, Nf2cells); // 2 way col count - SetLength(OrdMeansA, Nf1cells); // ordered means for factor 1 - SetLength(OrdMeansB, Nf2cells); // ordered means for factor 2 - if Calc2Way then - begin - lReport := TStringList.Create; - try - TwoWayTable(lReport); - TwoWayContrasts(lReport); - FReportFrame.DisplayReport(lReport); - TwoWayPlot; - finally - lReport.Free; - end; - end; -// vars := nil; -// sums := nil; -// counts := nil; - end; - - 3 : begin // three way anova - SetLength(RowSums, Nf1cells); // 2 way row sums - SetLength(ColSums, Nf2cells); // 2 way col sums - SetLength(RowCount, Nf1cells); // 2 way row count - SetLength(ColCount, Nf2cells); // 2 way col count - SetLength(SlcSums, Nf3cells); // 3 way slice sums - SetLength(SlcCount, Nf3cells); // 3 way slice counts - SetLength(OrdMeansA, Nf1cells); // ordered means for factor 1 - SetLength(OrdMeansB, Nf2cells); // ordered means for factor 2 - SetLength(OrdMeansC, Nf3cells); // ordered means for factor 3 - SetLength(wsum, Nf1cells, Nf2cells, Nf3cells); - SetLength(wx2, Nf1cells, Nf2cells, Nf3cells); - SetLength(ncnt, Nf1cells, Nf2cells, Nf3cells); - if Calc3Way then - begin - lReport := TStringList.Create; - try - ThreeWayTable(lReport); - ThreeWayContrasts(lReport); - FReportFrame.DisplayReport(lReport); - ThreeWayPlot; - finally - lReport.Free; - end; - { - ncnt := nil; - wx2 := nil; - wsum := nil; - OrdMeansC := nil; - SlcCount := nil; - SlcSums := nil; - } - end; - end; - end; // end switch -end; - - -procedure TOneCaseAnovaForm.Init; -var - i: Integer; - cellstring: String; -begin - comparisons := ScheffeChk.Checked or TukeyHSDChk.Checked or - TukeyBChk.Checked or TukeyKramerChk.Checked or NewmanKeulsChk.Checked; - - SSDep := 0.0; - SSF1 := 0.0; - SSF2 := 0.0; - SSF3 := 0.0; - SSF1F2 := 0.0; - SSF1F3 := 0.0; - SSF2F3 := 0.0; - SSF1F2F3 := 0.0; - MeanDep := 0.0; - MeanF1 := 0.0; - MeanF2 := 0.0; - MeanF3 := 0.0; - Nf1cells := 0; - Nf2cells := 0; - Nf3cells := 0; - //N := 0; - minf1 := 0; - maxf1 := 0; - minf2 := 0; - maxf2 := 0; - minf3 := 0; - maxf3 := 0; - // Get column numbers of dependent variable and factors SetLength(ColNoSelected, NoFactors + 1); // +1 because DepVar is at Index 0 ColNoSelected[0] := GetVariableIndex(OS3MainFrm.DataGrid, DepVarEdit.Text); @@ -441,18 +382,18 @@ begin ColNoSelected[2] := GetVariableIndex(OS3MainFrm.DataGrid, Factor2Edit.Text); if Factor3Edit.Text <> '' then ColNoSelected[3] := GetVariableIndex(OS3MainFrm.DataGrid, Factor3Edit.Text); - - OverAll := StrToFloat(OverAllAlphaEdit.Text); - PostHocAlpha := StrToFloat(PostAlphaEdit.Text); end; -procedure TOneCaseAnovaForm.GetLevels; +procedure TOneCaseAnovaForm.GetLevels(out DepValues, F1Values, F2Values, F3Values: DblDyneVec); var - i: integer; - intValue: Integer; mn, mx: Double; begin + DepValues := nil; + F1Values := nil; + F2Values := nil; + F3Values := nil; + // Extract dependent variable values DepValues := CollectVecValues(OS3MainFrm.DataGrid, ColNoSelected[0], ColNoSelected); @@ -480,73 +421,58 @@ begin NF3Cells := MaxF3 - MinF2 + 1; end else NF3Cells := 0; - - - // !!!!!!!!!!! wp: the following is needed only in the *Contrasts methods --> Move to there !!!!!!!!!!!!!!! - - TotalCells := NF1Cells + NF2Cells + NF3Cells; - - // allocate space - SetLength(CellCnts, TotalCells); // array of cell counts - SetLength(CellVars, TotalCells); // arrray of cell sums of squares variances - SetLength(CellSums, TotalCells); // array of cell sums means - - // initialize array values - for i := 0 to TotalCells-1 do - begin - CellSums[i] := 0.0; - CellVars[i] := 0.0; - CellCnts[i] := 0; - end; end; -function TOneCaseAnovaForm.Calc2Way: Boolean; +procedure TOneCaseAnovaForm.Init2Way; +begin + RowSums := nil; + ColSums := nil; + RowCount := nil; + ColCount := nil; + counts := nil; + sums := nil; + vars := nil; + + SetLength(RowSums, NF1Cells); // 2-way row sums + SetLength(ColSums, NF2Cells); // 2-way column sums + SetLength(RowCount, NF1Cells); // 2-way row counts + SetLength(ColCount, NF2Cells); // 2-way column counts + SetLength(counts, Nf1cells, Nf2cells); // matrix for 2-way containing cell sizes + SetLength(sums, Nf1cells, Nf2cells); // matrix for 2-way containing cell sums + SetLength(vars, Nf1cells, Nf2cells); // matrix for 2-way containing sums of squares +end; + + +function TOneCaseAnovaForm.Calc2Way(const DepValues, F1Values, F2Values: DblDyneVec): Boolean; var i, j, grpA, grpB: integer; - Constant, RowsTotCnt, ColsTotCnt, SSCells: double; + Constant, RowsTotCnt, ColsTotCnt: double; X, Xsq, rowMean, colmean: Double; begin // initialize matrix values NoGrpsA := MaxF1 - MinF1 + 1; NoGrpsB := MaxF2 - MinF2 + 1; - for i := 0 to NoGrpsA-1 do - begin - RowSums[i] := 0.0; - RowCount[i] := 0; - for j := 0 to NoGrpsB-1 do - begin - counts[i, j] := 0; - sums[i, j] := 0.0; - vars[i, j] := 0.0; - end; - end; - for i := 0 to NoGrpsB-1 do - begin - ColCount[i] := 0; - ColSums[i] := 0.0; - end; - - N := 0; - MeanDep := 0.0; - SSDep := 0.0; - SSCells := 0.0; - RowsTotCnt := 0.0; - ColsTotCnt := 0.0; - SSNonAdd := 0.0; - SSBalance := 0.0; - MSNonAdd := 0.0; - MSBalance := 0.0; + RowSums := Default(DblDyneVec); + ColSums := Default(DblDyneVec); + RowCount := Default(IntDyneVec); + ColCount := Default(IntDyneVec); + counts := Default(IntDyneMat); + sums := Default(DblDyneMat); + vars := Default(DblDyneMat); // Get working totals + N := 0; + MeanDep := 0; + SSDep := 0; for i := 0 to High(DepValues) do begin grpA := round(F1Values[i]) - MinF1; grpB := round(F2Values[i]) - MinF2; X := DepValues[i]; Xsq := X * X; - Counts[grpA, grpB] := counts[grpA, grpB] + 1; + Counts[grpA, grpB] := Counts[grpA, grpB] + 1; sums[grpA, grpB] := sums[grpA, grpB] + X; vars[grpA, grpB] := vars[grpA, grpB] + Xsq; RowSums[grpA] := RowSums[grpA] + X; @@ -557,35 +483,18 @@ begin SSDep := SSDep + Xsq; N := N + 1; end; - { - // get working totals - for i := 1 to NoCases do - begin - if not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected) then continue; - grpA := floor(StrToFloat(OS3MainFrm.DataGrid.Cells[F1Col,i])); - grpB := floor(StrToFloat(OS3MainFrm.DataGrid.Cells[F2Col,i])); - X := StrToFloat(OS3MainFrm.DataGrid.Cells[DepVarCol,i]); - grpA := grpA - minf1 + 1; - grpB := grpB - minf2 + 1; - counts[grpA-1,grpB-1] := counts[grpA-1,grpB-1] + 1; - sums[grpA-1,grpB-1] := sums[grpA-1,grpB-1] + X; - vars[grpA-1,grpB-1] := vars[grpA-1,grpB-1] + X * X; - RowSums[grpA-1] := RowSums[grpA-1] + X; - ColSums[grpB-1] := ColSums[grpB-1] + X; - RowCount[grpA-1] := RowCount[grpA-1] + 1; - ColCount[grpB-1] := ColCount[grpB-1] + 1; - MeanDep := MeanDep + X; - SSDep := SSDep + X * X; - N := N + 1; - end; - } // Calculate results + SSF1 := 0; + RowsTotCnt := 0; for i := 0 to NoGrpsA - 1 do begin SSF1 := SSF1 + sqr(RowSums[i]) / RowCount[i]; RowsTotCnt := RowsTotCnt + RowCount[i]; end; + + SSF2 := 0; + ColsTotCnt := 0; for j := 0 to NoGrpsB - 1 do begin SSF2 := SSF2 + sqr(ColSums[j]) / ColCount[j]; @@ -594,6 +503,7 @@ begin GrandMean := MeanDep / N; + SSNonAdd := 0; for i := 0 to NoGrpsA - 1 do begin rowmean := RowSums[i] / RowCount[i]; @@ -605,9 +515,10 @@ begin end; if (N > 0) then - Constant := (MeanDep * MeanDep) / N + Constant := sqr(MeanDep) / N else Constant := 0.0; + SSF1 := SSF1 - Constant; SSF2 := SSF2 - Constant; SSDep := SSDep - Constant; @@ -659,101 +570,102 @@ begin end; -procedure TOneCaseAnovaForm.TwoWayTable(AReport: TStrings); +procedure TOneCaseAnovaForm.TwoWayTable; var + lReport: TStrings; i, j, groupsize: integer; MinVar, MaxVar, sumvars, sumDFrecip, XBar, V, S, RowSS, ColSS: double; sumfreqlogvar: double; begin - if CompError then - exit; + lReport := TStringList.Create; + try + lReport.Add('TWO-WAY ANALYSIS OF VARIANCE'); + lReport.Add(''); + lReport.Add('Variable analyzed: %s', [DepVarEdit.Text]); + lReport.Add(''); + lReport.Add('Factor A (rows) variable: %s', [Factor1Edit.Text]); + lReport.Add('Factor B (columns) variable: %s', [Factor2Edit.Text]); + lReport.Add(''); + lReport.Add('SOURCE D.F. SS MS F PROB.> F Omega Squared'); + lReport.Add('-------------- ---- ------------ ------------ ---------- -------- -------------'); + lReport.Add('Among Rows %4.0f %12.3f %12.3f %10.3f %8.3f %10.3f', [DFF1, SSF1, MSF1, FF1, ProbF1, OmegaF1]); + lReport.Add('Among Columns %4.0f %12.3f %12.3f %10.3f %8.3f %10.3f', [DFF2, SSF2, MSF2, FF2, ProbF2, OmegaF2]); + lReport.Add('Residual %4.0f %12.3f %12.3f', [DFErr, SSErr, MSErr]); + lReport.Add(' NonAdditivity %4.0f %12.3f %12.3f %10.3f %8.3f', [1.0, SSNonAdd, MSNonAdd, FNonAdd, ProbNonAdd]); + lReport.Add(' Balance %4.0f %12.3f %12.3f', [DFBalance, SSBalance, MSBalance]); + lReport.Add('Total %4.0f %12.3f %12.3f', [DFTot, SSDep, MSDep]); + lReport.Add(''); + lReport.Add('Omega squared for combined effects: %10.3f', [Omega]); + lReport.Add(''); + lReport.Add('DESCRIPTIVE STATISTICS'); + lReport.Add(''); + lReport.Add('GROUP Row Col. N MEAN VARIANCE STD.DEV.'); + lReport.Add('----- --- ---- ---- -------- -------- ---------'); - AReport.Add('TWO-WAY ANALYSIS OF VARIANCE'); - AReport.Add(''); - AReport.Add('Variable analyzed: %s', [DepVarEdit.Text]); - AReport.Add(''); - AReport.Add('Factor A (rows) variable: %s', [Factor1Edit.Text]); - AReport.Add('Factor B (columns) variable: %s', [Factor2Edit.Text]); - AReport.Add(''); - AReport.Add('SOURCE D.F. SS MS F PROB.> F Omega Squared'); - AReport.Add('-------------- ---- ------------ ------------ ---------- -------- -------------'); - AReport.Add('Among Rows %4.0f %12.3f %12.3f %10.3f %8.3f %10.3f', [DFF1, SSF1, MSF1, FF1, ProbF1, OmegaF1]); - AReport.Add('Among Columns %4.0f %12.3f %12.3f %10.3f %8.3f %10.3f', [DFF2, SSF2, MSF2, FF2, ProbF2, OmegaF2]); - AReport.Add('Residual %4.0f %12.3f %12.3f', [DFErr, SSErr, MSErr]); - AReport.Add(' NonAdditivity %4.0f %12.3f %12.3f %10.3f %8.3f', [1.0, SSNonAdd, MSNonAdd, FNonAdd, ProbNonAdd]); - AReport.Add(' Balance %4.0f %12.3f %12.3f', [DFBalance, SSBalance, MSBalance]); - AReport.Add('Total %4.0f %12.3f %12.3f', [DFTot, SSDep, MSDep]); - AReport.Add(''); - AReport.Add('Omega squared for combined effects: %10.3f', [Omega]); - AReport.Add(''); - AReport.Add('DESCRIPTIVE STATISTICS'); - AReport.Add(''); - AReport.Add('GROUP Row Col. N MEAN VARIANCE STD.DEV.'); - AReport.Add('----- --- ---- ---- -------- -------- ---------'); + groupsize := ceil(counts[0,0]); + equal_grp := true; + MaxVar := -1e308; + MinVar := 1e308; + sumvars := 0.0; + sumfreqlogvar := 0.0; + sumDFrecip := 0.0; - groupsize := ceil(counts[0,0]); - equal_grp := true; - MaxVar := -1e308; - MinVar := 1e308; - sumvars := 0.0; - sumfreqlogvar := 0.0; - sumDFrecip := 0.0; + // Display cell means, variances, standard deviations + for i := 0 to NoGrpsA - 1 do + begin + for j := 0 to NoGrpsB - 1 do + begin + if (counts[i,j] > 1) then + begin + XBar := sums[i, j] / counts[i, j]; + V := vars[i, j] - sqr(sums[i, j]) / counts[i, j]; + V := V / (counts[i, j] - 1.0); + S := sqrt(V); + sumvars := sumvars + V; + if (V > MaxVar) then MaxVar := V; + if (V < MinVar) then MinVar := V; + sumDFrecip := sumDFrecip + 1.0 / (counts[i, j] - 1.0); + sumFreqLogVar := sumFreqLogVar + (counts[i,j] - 1.0) * ln(V); + if (counts[i, j] <> groupsize) then equal_grp := false; + end + else + XBar := sums[i, j]; + lReport.Add('Cell %3d %3d %3d %8.3f %8.3f %8.3f', [minf1+i, minf2+j, counts[i, j], XBar, V, S]); + end; + end; - // Display cell means, variances, standard deviations - V := 0.0; - XBar := 0.0; - S := 0.0; - for i := 0 to NoGrpsA - 1 do - begin + //Display Row means, variances, standard deviations + for i := 0 to NoGrpsA - 1 do + begin + XBar := RowSums[i] / RowCount[i]; + // OrdMeansA[i] := XBar; + RowSS := 0.0; + for j := 0 to NoGrpsB - 1 do RowSS := RowSS + vars[i,j]; + V := RowSS - sqr(RowSums[i]) / RowCount[i]; + V := V / (RowCount[i] - 1.0); + S := sqrt(V); + lReport.Add('Row %3d %3d %8.3f %8.3f %8.3f', [minf1+i, RowCount[i], XBar, V, S]); + end; + + //Display means, variances and standard deviations for columns for j := 0 to NoGrpsB - 1 do begin - if (counts[i,j] > 1) then - begin - XBar := sums[i, j] / counts[i, j]; - V := vars[i, j] - sqr(sums[i, j]) / counts[i, j]; - V := V / (counts[i, j] - 1.0); - S := sqrt(V); - sumvars := sumvars + V; - if (V > MaxVar) then MaxVar := V; - if (V < MinVar) then MinVar := V; - sumDFrecip := sumDFrecip + 1.0 / (counts[i, j] - 1.0); - sumfreqlogvar := sumfreqlogvar + (counts[i,j] - 1.0) * ln(V); - if (counts[i, j] <> groupsize) then equal_grp := false; - end - else - XBar := sums[i][j]; - AReport.Add('Cell %3d %3d %3d %8.3f %8.3f %8.3f', [minf1+i, minf2+j, counts[i,j], XBar, V, S]); + XBar := ColSums[j] / ColCount[j]; + // OrdMeansB[j] := XBar; + ColSS := 0.0; + for i := 0 to NoGrpsA - 1 do ColSS := ColSS + vars[i,j]; + if (ColCount[j] > 0) then V := ColSS - sqr(ColSums[j]) / ColCount[j]; + if (ColCount[j] > 1) then V := V / (ColCount[j] - 1.0); + if (V > 0.0) then S := sqrt(V); + lReport.Add('Col %3d %3d %8.3f %8.3f %8.3f', [minf2+j, ColCount[j], XBar, V, S]); end; - end; - //Display Row means, variances, standard deviations - for i := 0 to NoGrpsA - 1 do - begin - XBar := RowSums[i] / RowCount[i]; - OrdMeansA[i] := XBar; - RowSS := 0.0; - for j := 0 to NoGrpsB - 1 do RowSS := RowSS + vars[i,j]; - V := RowSS - sqr(RowSums[i]) / RowCount[i]; - V := V / (RowCount[i] - 1.0); - S := sqrt(V); - AReport.Add('Row %3d %3d %8.3f %8.3f %8.3f', [minf1+i, RowCount[i], XBar, V, S]); - end; + lReport.Add('TOTAL %3d %8.3f %8.3f %8.3f', [N, MeanDep, MSDep, sqrt(MSDep)]); - //Display means, variances and standard deviations for columns - for j := 0 to NoGrpsB - 1 do - begin - XBar := ColSums[j] / ColCount[j]; - OrdMeansB[j] := XBar; - ColSS := 0.0; - for i := 0 to NoGrpsA - 1 do ColSS := ColSS + vars[i,j]; - if (ColCount[j] > 0) then V := ColSS - sqr(ColSums[j]) / ColCount[j]; - if (ColCount[j] > 1) then V := V / (ColCount[j] - 1.0); - if (V > 0.0) then S := sqrt(V); - AReport.Add('Col %3d %3d %8.3f %8.3f %8.3f', [minf2+j, ColCount[j], XBar, V, S]); + FReportFrame.DisplayReport(lReport); + finally + lReport.Free; end; - - AReport.Add('TOTAL %3d %8.3f %8.3f %8.3f', [N, MeanDep, MSDep, sqrt(MSDep)]); - AReport.Add(''); end; @@ -772,30 +684,32 @@ begin FChartCombobox.Items.Add(a); FChartCombobox.Items.Add(b); if ThreeWay then - begin FChartCombobox.Items.Add(c); - for i := 0 to NF3Cells-1 do - FChartCombobox.Items.Add(Format('%s * %s vs %s with %s=%d', [a, b, a, c, Round(MinF3) + i])); - for i := 0 to NF3Cells-1 do - FChartCombobox.Items.Add(Format('%s * %s vs %s with %s=%d', [a, b, b, c, Round(MinF3) + i])); - for i := 0 to NF2Cells-1 do - FChartCombobox.Items.Add(Format('%s * %s vs %s with %s=%d', [a, c, a, b, Round(MinF2) + i])); - for i := 0 to NF2Cells-1 do - FChartCombobox.Items.Add(Format('%s * %s vs %s with %s=%d', [a, c, c, b, Round(MinF2) + i])); - for i := 0 to NF1Cells-1 do - FChartCombobox.Items.Add(Format('%s * %s vs %s with %s=%d', [b, c, b, a, Round(MinF1) + i])); - for i := 0 to NF1Cells-1 do - FChartCombobox.Items.Add(Format('%s * %s vs %s with %s=%d', [b, c, c, a, Round(MinF1) + i])); - end else + + if InteractChk.Checked then begin - FChartCombobox.Items.Add(Format('Interaction %s*%s vs %s', [a, b, a])); - FChartCombobox.Items.Add(Format('Interaction %s*%s vs %s', [a, b, b])); + if ThreeWay then + begin + for i := 0 to NF3Cells-1 do + FChartCombobox.Items.Add(Format('%s * %s vs %s with %s=%d', [a, b, a, c, Round(MinF3) + i])); + for i := 0 to NF3Cells-1 do + FChartCombobox.Items.Add(Format('%s * %s vs %s with %s=%d', [a, b, b, c, Round(MinF3) + i])); + for i := 0 to NF2Cells-1 do + FChartCombobox.Items.Add(Format('%s * %s vs %s with %s=%d', [a, c, a, b, Round(MinF2) + i])); + for i := 0 to NF2Cells-1 do + FChartCombobox.Items.Add(Format('%s * %s vs %s with %s=%d', [a, c, c, b, Round(MinF2) + i])); + for i := 0 to NF1Cells-1 do + FChartCombobox.Items.Add(Format('%s * %s vs %s with %s=%d', [b, c, b, a, Round(MinF1) + i])); + for i := 0 to NF1Cells-1 do + FChartCombobox.Items.Add(Format('%s * %s vs %s with %s=%d', [b, c, c, a, Round(MinF1) + i])); + end else + begin + FChartCombobox.Items.Add(Format('%s * %s vs %s', [a, b, a])); + FChartCombobox.Items.Add(Format('%s * %s vs %s', [a, b, b])); + end; end; - if idx = -1 then - FChartCombobox.ItemIndex := 0 - else - FChartCombobox.ItemIndex := Min(idx, FChartCombobox.Items.Count-1);; + FChartComboBox.ItemIndex := EnsureRange(idx, 0, FChartComboBox.Items.Count-1); end; @@ -812,13 +726,13 @@ begin FSeries.ListSource.YCount := 1; for i := 0 to NF1Cells-1 do FSeries.AddXY(minF1 + i, RowSums[i] / RowCount[i], IntToStr(MinF1 + i)); - FChartFrame.SetXTitle(Factor1Edit.Text); + FChartFrame.SetXTitle(Factor1Edit.Text + ' codes'); end; 1: begin // Plot means vs factor B FSeries.ListSource.YCount := 1; for j := 0 to NF2Cells-1 do FSeries.AddXY(minF2 + j, ColSums[j] / ColCount[j], IntToStr(MinF2 + j)); - FChartFrame.SetXTitle(Factor2Edit.Text); + FChartFrame.SetXTitle(Factor2Edit.Text + ' codes'); end; 2: begin // Plot interaction A*B vs A FSeries.ListSource.YCount := NF2Cells; @@ -829,7 +743,7 @@ begin for j := 0 to NF2Cells-1 do item^.SetY(j, sums[i, j] / counts[i, j]); end; - FChartFrame.SetXTitle(Factor1Edit.Text); + FChartFrame.SetXTitle(Factor1Edit.Text + ' codes'); for j := 0 to NF2cells-1 do with TChartStyle(FStyles.Styles.Add) do begin @@ -847,7 +761,7 @@ begin for i := 0 to NF1Cells-1 do item^.SetY(i, sums[i, j] / counts[i, j]); end; - FChartFrame.SetXTitle(Factor2Edit.Text); + FChartFrame.SetXTitle(Factor2Edit.Text + ' codes'); for i := 0 to NF1Cells-1 do with TChartStyle(FStyles.styles.Add) do begin @@ -876,192 +790,72 @@ end; procedure TOneCaseAnovaForm.TwoWayPlot; begin + if not ShowPlotsChk.Checked then + begin + ChartPage.TabVisible := false; + exit; + end; + FChartFrame.Clear; // this destroys the series FChartFrame.SetYTitle('Means'); FSeries := FChartFrame.PlotXY(ptBars, nil, nil, nil, nil, '', DATA_COLORS[0]); - TBarSeries(FSeries).Stacked := false; + with TBarSeries(FSeries) do + begin + Stacked := false; + {$IF LCL_FullVersion >= 2010000} + DepthBrightnessDelta := -30; + {$IFEND} + end; + if Plot3DChk.Checked then + FSeries.Depth := 20; PopulateChartCombobox(false); FChartCombobox.OnChange := @SelectTwoWayPlot; SelectTwoWayPlot(nil); + + ChartPage.TabVisible := true; end; -(* -procedure TOneCaseAnovaForm.TwoWayPlot; -var - i, j: integer; - maxmean, XBar: double; - XValue: DblDyneVec = nil; - plottype: integer; + +procedure TOneCaseAnovaForm.Init3Way; begin - if CompError then - exit; + RowSums := nil; + ColSums := nil; + RowCount := nil; + ColCount := nil; + SlcSums := nil; + SlcCount := nil; + wsum := nil; + wx2 := nil; + ncnt := nil; - case PlotOptionsGroup.ItemIndex of - 0: exit; - 1: plotType := 2; // 3D bars - 2: plotType := 1; // 2D bars - 3: plotType := 9; // 2D horizontal bars - else raise Exception.Create('Plot type not supported.'); - end; - - SetLength(XValue, Nf1cells+Nf2cells); - - // Factor A first - GraphFrm.SetLabels[1] := 'FACTOR A'; - maxmean := 0.0; - SetLength(GraphFrm.Xpoints, 1, Nf1cells); - SetLength(GraphFrm.Ypoints, 1, Nf1cells); - for i := 1 to Nf1cells do - begin - RowSums[i-1] := RowSums[i-1] / RowCount[i-1]; - GraphFrm.Ypoints[0,i-1] := RowSums[i-1]; - if (RowSums[i-1] > maxmean) then maxmean := RowSums[i-1]; - XValue[i-1] := minf1 + i - 1; - GraphFrm.Xpoints[0,i-1] := XValue[i-1]; - end; - GraphFrm.nosets := 1; - GraphFrm.nbars := Nf1cells; - GraphFrm.Heading := Factor1Edit.Text; - GraphFrm.XTitle := Factor1Edit.Text + ' Codes'; - GraphFrm.YTitle := 'Mean'; - GraphFrm.barwideprop := 0.5; - GraphFrm.AutoScaled := false; - GraphFrm.miny := 0.0; - GraphFrm.maxy := maxmean; - GraphFrm.GraphType := plottype; - GraphFrm.BackColor := clCream; - GraphFrm.WallColor := clDkGray; - GraphFrm.FloorColor := clLtGray; - GraphFrm.ShowBackWall := true; - GraphFrm.ShowModal(); - GraphFrm.Xpoints := nil; - GraphFrm.Ypoints := nil; - - // Factor B next - GraphFrm.SetLabels[1] := 'FACTOR B'; - maxmean := 0.0; - SetLength(GraphFrm.Xpoints, 1, Nf2cells); - SetLength(GraphFrm.Ypoints, 1, Nf2cells); - for i := 1 to Nf2cells do - begin - ColSums[i-1] := ColSums[i-1] / ColCount[i-1]; - GraphFrm.Ypoints[0,i-1] := ColSums[i-1]; - if (ColSums[i-1] > maxmean) then maxmean := ColSums[i-1]; - XValue[i-1] := minf1 + i - 1; - GraphFrm.Xpoints[0,i-1] := XValue[i-1]; - end; - GraphFrm.nosets := 1; - GraphFrm.nbars := Nf2cells; - GraphFrm.Heading := Factor2Edit.Text; - GraphFrm.XTitle := Factor2Edit.Text + ' Codes'; - GraphFrm.YTitle := 'Mean'; - GraphFrm.barwideprop := 0.5; - GraphFrm.AutoScaled := false; - GraphFrm.miny := 0.0; - GraphFrm.maxy := maxmean; - GraphFrm.GraphType := plottype; - GraphFrm.BackColor := clCream; - GraphFrm.WallColor := clDkGray; - GraphFrm.FloorColor := clLtGray; - GraphFrm.ShowBackWall := true; - GraphFrm.ShowModal(); - GraphFrm.Xpoints := nil; - GraphFrm.Ypoints := nil; - - // Factor A x B Interaction next - maxmean := 0.0; - SetLength(GraphFrm.Ypoints, Nf1cells, Nf2cells); - SetLength(GraphFrm.Xpoints, 1, Nf2cells); - for i := 1 to Nf1cells do - begin - GraphFrm.SetLabels[i] := Factor1Edit.Text + ' ' + IntToStr(i); - for j := 1 to Nf2cells do - begin - XBar := sums[i-1,j-1] / counts[i-1,j-1]; - if (XBar > maxmean) then maxmean := XBar; - GraphFrm.Ypoints[i-1,j-1] := XBar; - end; - end; - for j := 1 to Nf2cells do - begin - XValue[j-1] := minf2 + j - 1; - GraphFrm.Xpoints[0,j-1] := XValue[j-1]; - end; - GraphFrm.nosets := Nf1cells; - GraphFrm.nbars := Nf2cells; - GraphFrm.Heading := 'Factor A x Factor B'; - GraphFrm.XTitle := Factor2Edit.Text + ' Codes'; - GraphFrm.YTitle := 'Mean'; - GraphFrm.barwideprop := 0.5; - GraphFrm.AutoScaled := false; - GraphFrm.miny := 0.0; - GraphFrm.maxy := maxmean; - GraphFrm.GraphType := plottype; - GraphFrm.BackColor := clCream; - GraphFrm.WallColor := clDkGray; - GraphFrm.FloorColor := clLtGray; - GraphFrm.ShowBackWall := true; - GraphFrm.ShowModal(); - XValue := nil; - GraphFrm.Xpoints := nil; - GraphFrm.Ypoints := nil; + SetLength(RowSums, NF1Cells); // 2-way row sums + SetLength(ColSums, NF2Cells); // 2-way column sums + SetLength(RowCount, NF1Cells); // 2-way row counts + SetLength(ColCount, NF2Cells); // 2-way column counts + SetLength(SlcSums, Nf3cells); // 3 way slice sums + SetLength(SlcCount, Nf3cells); // 3 way slice counts + SetLength(wsum, Nf1cells, Nf2cells, Nf3cells); + SetLength(wx2, Nf1cells, Nf2cells, Nf3cells); + SetLength(ncnt, Nf1cells, Nf2cells, Nf3cells); end; - *) -function TOneCaseAnovaForm.Calc3Way: Boolean; + +function TOneCaseAnovaForm.Calc3Way(const DepValues, + F1Values, F2Values, F3Values: DblDyneVec): Boolean; var i, j, k, grpA, grpB, grpC: integer; - Constant, RowsTotCnt, ColsTotCnt, SlcsTotCnt, SSCells, p, n2: double; + Constant, RowsTotCnt, ColsTotCnt, SlcsTotCnt, p, n2: double; X, Xsq, rowMean, colMean, sliceMean: Double; begin // initialize matrix values NoGrpsA := maxf1 - minf1 + 1; NoGrpsB := maxf2 - minf2 + 1; NoGrpsC := maxf3 - minf3 + 1; - for i := 0 to NoGrpsA - 1 do - begin - RowSums[i] := 0.0; - RowCount[i] := 0; - for j := 0 to NoGrpsB - 1 do - begin - for k := 0 to NoGrpsC - 1 do - begin - wsum[i,j,k] := 0.0; - ncnt[i,j,k] := 0; - wx2[i,j,k] := 0.0; - end; - end; - end; - - for i := 0 to NoGrpsB - 1 do - begin - ColCount[i] := 0; - ColSums[i] := 0.0; - end; - - for i := 0 to NoGrpsC - 1 do - begin - SlcCount[i] := 0; - SlcSums[i] := 0; - end; - - N := 0; - MeanDep := 0.0; - SSDep := 0.0; - RowsTotCnt := 0.0; - ColsTotCnt := 0.0; - SlcsTotCnt := 0.0; - SSF1 := 0.0; - SSF2 := 0.0; - SSF3 := 0.0; - SSF1F2 := 0.0; - SSF1F3 := 0.0; - SSF2F3 := 0.0; - SSF1F2F3 := 0.0; - SSCells := 0.0; - SSNonAdd := 0.0; // Get working totals + N := 0; + MeanDep := 0; + SSDep := 0; for i := 0 to High(DepValues) do begin grpA := round(F1Values[i]) - MinF1; @@ -1083,38 +877,13 @@ begin N := N + 1; end; - { - // get working totals - for i := 1 to NoCases do - begin - if not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected) then continue; - grpA := floor(StrToFloat(OS3MainFrm.DataGrid.Cells[ColNoSelected[1],i])); - grpB := floor(StrToFloat(OS3MainFrm.DataGrid.Cells[ColNoSelected[2],i])); - grpC := floor(StrToFloat(OS3MainFrm.DataGrid.Cells[ColNoSelected[3],i])); - X := StrToFloat(OS3MainFrm.DataGrid.Cells[ColNoSelected[0],i]); - grpA := grpA - minf1 + 1; - grpB := grpB - minf2 + 1; - grpC := grpC - minf3 + 1; - ncnt[grpA-1,grpB-1,grpC-1] := ncnt[grpA-1,grpB-1,grpC-1] + 1; - wsum[grpA-1,grpB-1,grpC-1] := wsum[grpA-1,grpB-1,grpC-1] + X; - wx2[grpA-1,grpB-1,grpC-1] := wx2[grpA-1,grpB-1,grpC-1] + X * X; - RowSums[grpA-1] := RowSums[grpA-1] + X; - ColSums[grpB-1] := ColSums[grpB-1] + X; - SlcSums[grpC-1] := SlcSums[grpC-1] + X; - RowCount[grpA-1] := RowCount[grpA-1] + 1; - ColCount[grpB-1] := ColCount[grpB-1] + 1; - SlcCount[grpC-1] := SlcCount[grpC-1] + 1; - MeanDep := MeanDep + X; - SSDep := SSDep + X * X; - N := N + 1; - end; - } - // Calculate results - Constant := (MeanDep * MeanDep) / N; + Constant := sqr(MeanDep) / N; GrandMean := MeanDep / N; // Get ss for rows + SSF1 := 0; + RowsTotCnt := 0; for i := 0 to NoGrpsA - 1 do begin SSF1 := SSF1 + RowSums[i] * RowSums[i] / RowCount[i]; @@ -1123,6 +892,8 @@ begin SSF1 := SSF1 - Constant; // Get ss for columns + SSF2 := 0; + ColsTotCnt := 0; for j := 0 to NoGrpsB - 1 do begin SSF2 := SSF2 + ColSums[j] * ColSums[j] / ColCount[j]; @@ -1131,6 +902,8 @@ begin SSF2 := SSF2 - Constant; // Get ss for slices + SSF3 := 0; + SlcsTotCnt := 0; for k := 0 to NoGrpsC - 1 do begin SSF3 := SSF3 + SlcSums[k] * SlcSums[k] / SlcCount[k]; @@ -1141,6 +914,7 @@ begin // Get ss for row x col interaction p := 0.0; n2 := 0.0; + SSF1F2 := 0; for i := 0 to NoGrpsA - 1 do begin for j := 0 to NoGrpsB - 1 do @@ -1151,13 +925,14 @@ begin n2 := n2 + ncnt[i,j,k]; end; SSF1F2 := SSF1F2 + p * p / n2; - p := 0.0; - n2 := 0.0; end; end; SSF1F2 := SSF1F2 - SSF1 - SSF2 - Constant; // Get ss for row x slice interaction + SSF1F3 := 0; + p := 0.0; + n2 := 0.0; for i := 0 to NoGrpsA - 1 do begin for k := 0 to NoGrpsC - 1 do @@ -1168,13 +943,14 @@ begin n2 := n2 + ncnt[i,j,k]; end; SSF1F3 := SSF1F3 + p * p / n2; - p := 0.0; - n2 := 0.0; end; end; SSF1F3 := SSF1F3 - SSF1 - SSF3 - Constant; // Get ss for columns x slices interaction + SSF2F3 := 0; + p := 0.0; + n2 := 0.0; for j := 0 to NoGrpsB - 1 do begin for k := 0 to NoGrpsC - 1 do @@ -1191,16 +967,7 @@ begin end; SSF2F3 := SSF2F3 - SSF2 - SSF3 - Constant; -(* - // get ss for cells - for (i := 0; i < NoGrpsA; i++) - for (j := 0; j < NoGrpsB; j++) - for (k := 0; k < NoGrpsC; k++) - SSCells := SSCells + ((wsum[i][j][k] * wsum[i][j][k]) / ncnt[i][j][k]); - - SSF1F2F3 := SSCells - SSF1 - SSF2 - SSF3 - SSF1F2 - SSF1F3 - SSF2F3 - Constant; -*) - + SSNonAdd := 0; for i := 0 to NoGrpsA - 1 do begin rowmean := RowSums[i] / RowCount[i]; @@ -1209,8 +976,8 @@ begin colmean := ColSums[j] / ColCount[j]; for k := 0 to NoGrpsC - 1 do begin - slicemean := SlcSums[k] / SlcCount[k]; - SSNonAdd := SSNonAdd + (colmean-GrandMean) * (rowmean-GrandMean) * (slicemean-GrandMean) * wsum[i,j,k]; + sliceMean := SlcSums[k] / SlcCount[k]; + SSNonAdd := SSNonAdd + (colmean-GrandMean) * (rowmean-GrandMean) * (sliceMean-GrandMean) * wsum[i,j,k]; end; end; end; @@ -1227,7 +994,7 @@ begin if ((SSF1 < 0.0) or (SSF2 < 0.0) or (SSF3 < 0.0) or (SSF1F2 < 0.0) or (SSF1F3 < 0.0) or (SSF2F3 < 0.0)) then begin - ErrorMsg('A negative SS found. Unbalanced Design? Ending analysis.'); + ErrorMsg('A negative SS found. Unbalanced design? Ending analysis.'); Result := false; exit; end; @@ -1304,112 +1071,99 @@ begin end; -procedure TOneCaseAnovaForm.ThreeWayTable(AReport: TStrings); +procedure TOneCaseAnovaForm.ThreeWayTable; var + lReport: TStrings; i, j, k: integer; XBar, V, S, RowSS, ColSS, SlcSS: double; begin - if CompError then - exit; + lReport := TStringList.Create; + try + lReport.Add('THREE-WAY ANALYSIS OF VARIANCE'); + lReport.Add(''); + lReport.Add('Variable analyzed: %s', [DepVarEdit.Text]); + lReport.Add(''); + lReport.Add('Factor A (rows) variable: %s', [Factor1Edit.Text]); + lReport.Add('Factor B (columns) variable: %s', [Factor2Edit.Text]); + lReport.Add('Factor C (slices) variable: %s', [Factor3Edit.Text]); + lReport.Add(''); + lReport.Add('SOURCE D.F. SS MS F PROB.> F Omega Squared'); + lReport.Add(''); + lReport.Add('Among Rows %4.0f %12.4f %12.4f %12.4f %6.3f %6.3f', [DFF1, SSF1, MSF1, FF1, ProbF1, OmegaF1]); + lReport.Add('Among Columns %4.0f %12.4f %12.4f %12.4f %6.3f %6.3f', [DFF2, SSF2, MSF2, FF2, ProbF2, OmegaF2]); + lReport.Add('Among Slices %4.0f %12.4f %12.4f %12.4f %6.3f %6.3f', [DFF3, SSF3, MSF3, FF3, ProbF3, OmegaF3]); - AReport.Add('THREE-WAY ANALYSIS OF VARIANCE'); - AReport.Add(''); - AReport.Add('Variable analyzed: %s', [DepVarEdit.Text]); - AReport.Add(''); - AReport.Add('Factor A (rows) variable: %s', [Factor1Edit.Text]); - AReport.Add('Factor B (columns) variable: %s', [Factor2Edit.Text]); - AReport.Add('Factor C (slices) variable: %s', [Factor3Edit.Text]); - AReport.Add(''); - AReport.Add('SOURCE D.F. SS MS F PROB.> F Omega Squared'); - AReport.Add(''); - AReport.Add('Among Rows %4.0f %12.4f %12.4f %12.4f %6.3f %6.3f', [DFF1, SSF1, MSF1, FF1, ProbF1, OmegaF1]); - AReport.Add('Among Columns %4.0f %12.4f %12.4f %12.4f %6.3f %6.3f', [DFF2, SSF2, MSF2, FF2, ProbF2, OmegaF2]); - AReport.Add('Among Slices %4.0f %12.4f %12.4f %12.4f %6.3f %6.3f', [DFF3, SSF3, MSF3, FF3, ProbF3, OmegaF3]); + if InteractChk.Checked then + begin + lReport.Add('A x B Inter. %4.0f %12.4f %12.4f %12.4f %6.3f %6.3f', [DFF1F2, SSF1F2, MSF1F2, FF1F2, ProbF1F2, OmegaF1F2]); + lReport.Add('A x C Inter. %4.0f %12.4f %12.4f %12.4f %6.3f %6.3f', [DFF1F3, SSF1F3, MSF1F3, FF1F3, ProbF1F3, OmegaF1F3]); + lReport.Add('B x C Inter. %4.0f %12.4f %12.4f %12.4f %6.3f %6.3f', [DFF2F3, SSF2F3, MSF2F3, FF2F3, ProbF2F3, OmegaF2F3]); + end; + lReport.Add('Residual %4.0f %12.4f %12.4f', [DFErr, SSErr, MSErr]); + lReport.Add(' NonAdditivity %4.0f %12.4f %12.4f %12.4f %6.3f', [1.0, SSNonAdd, MSNonAdd, FNonAdd, ProbNonAdd]); + lReport.Add(' Balance %4.0f %12.4f %12.4f', [DFBalance, SSBalance, MSBalance]); + lReport.Add('Total %4.0f %12.4f %12.4f', [DFTot, SSDep, MSDep]); + lReport.Add(''); + lReport.Add('Omega squared for combined effects := %8.4f', [Omega]); + lReport.Add(''); + lReport.Add(''); + lReport.Add('DESCRIPTIVE STATISTICS'); + lReport.Add(''); + lReport.Add('GROUP N MEAN VARIANCE STD.DEV.'); + equal_grp := true; - if InteractChk.Checked then - begin - AReport.Add('A x B Inter. %4.0f %12.4f %12.4f %12.4f %6.3f %6.3f', [DFF1F2, SSF1F2, MSF1F2, FF1F2, ProbF1F2, OmegaF1F2]); - AReport.Add('A x C Inter. %4.0f %12.4f %12.4f %12.4f %6.3f %6.3f', [DFF1F3, SSF1F3, MSF1F3, FF1F3, ProbF1F3, OmegaF1F3]); - AReport.Add('B x C Inter. %4.0f %12.4f %12.4f %12.4f %6.3f %6.3f', [DFF2F3, SSF2F3, MSF2F3, FF2F3, ProbF2F3, OmegaF2F3]); - end; - AReport.Add('Residual %4.0f %12.4f %12.4f', [DFErr, SSErr, MSErr]); - AReport.Add(' NonAdditivity %4.0f %12.4f %12.4f %12.4f %6.3f', [1.0, SSNonAdd, MSNonAdd, FNonAdd, ProbNonAdd]); - AReport.Add(' Balance %4.0f %12.4f %12.4f', [DFBalance, SSBalance, MSBalance]); - AReport.Add('Total %4.0f %12.4f %12.4f', [DFTot, SSDep, MSDep]); - AReport.Add(''); - AReport.Add('Omega squared for combined effects := %8.4f', [Omega]); - AReport.Add(''); - AReport.Add(''); - AReport.Add('Descriptive Statistics'); - AReport.Add(''); - AReport.Add('GROUP N MEAN VARIANCE STD.DEV.'); - equal_grp := true; + //Display Row means, variances, standard deviations + for i := 0 to NoGrpsA - 1 do + begin + XBar := RowSums[i] / RowCount[i]; + RowSS := 0.0; + for j := 0 to NoGrpsB - 1 do + for k := 0 to NoGrpsC - 1 do + RowSS := RowSS + wx2[i,j,k]; + V := (RowSS - sqr(RowSums[i]) / RowCount[i]) / (RowCount[i] - 1);; + S := sqrt(V); + lReport.Add('Row %3d %3d %8.3f %8.3f %8.3f', [minf1+i, RowCount[i], XBar, V, S]); + end; - // Display cell means, variances, standard deviations - for i := 0 to NoGrpsA - 1 do - begin + //Display means, variances and standard deviations for columns for j := 0 to NoGrpsB - 1 do begin - for k := 0 to NoGrpsC - 1 do - begin - XBar := wsum[i,j,k] / ncnt[i,j,k]; // wp: why this? Result is not used and overwritten in next loop. - V := 0.0; // dto. - S := 0.0; // dto. - end; + XBar := ColSums[j] / ColCount[j]; + ColSS := 0.0; + for i := 0 to NoGrpsA - 1 do + for k := 0 to NoGrpsC - 1 do + ColSS := ColSS + wx2[i,j,k]; + V := (ColSS - sqr(ColSums[j]) / ColCount[j]) / (ColCount[j] - 1); + S := sqrt(V); + lReport.Add('Col %3d %3d %8.3f %8.3f %8.3f', [minf2+j, ColCount[j], XBar, V, S]); end; - end; - //Display Row means, variances, standard deviations - for i := 0 to NoGrpsA - 1 do - begin - XBar := RowSums[i] / RowCount[i]; - OrdMeansA[i] := XBar; - RowSS := 0.0; - for j := 0 to NoGrpsB - 1 do - for k := 0 to NoGrpsC - 1 do - RowSS := RowSS + wx2[i,j,k]; - V := RowSS - (RowSums[i] * RowSums[i] / RowCount[i]); - V := V / (RowCount[i] - 1.0); - S := sqrt(V); - AReport.Add('Row %3d %3d %8.3f %8.3f %8.3f', [minf1+i, RowCount[i], XBar, V, S]); - end; + //Display means, variances and standard deviations for slices + for k := 0 to NoGrpsC - 1 do + begin + XBar := SlcSums[k] / SlcCount[k]; + SlcSS := 0.0; + for i := 0 to NoGrpsA - 1 do + for j := 0 to NoGrpsB - 1 do + SlcSS := SlcSS + wx2[i,j,k]; + V := (SlcSS - sqr(SlcSums[k]) / SlcCount[k]) / (SlcCount[k] - 1); + S := sqrt(V); + lReport.Add('Slice %3d %3d %8.3f %8.3f %8.3f', [minf3+k, SlcCount[k], XBar, V, S]); + end; - //Display means, variances and standard deviations for columns - for j := 0 to NoGrpsB - 1 do - begin - XBar := ColSums[j] / ColCount[j]; - OrdMeansB[j] := XBar; - ColSS := 0.0; - for i := 0 to NoGrpsA - 1 do - for k := 0 to NoGrpsC - 1 do - ColSS := ColSS + wx2[i,j,k]; - V := ColSS - (ColSums[j] * ColSums[j] / ColCount[j]); - V := V / (ColCount[j] - 1.0); - S := sqrt(V); - AReport.Add('Col %3d %3d %8.3f %8.3f %8.3f', [minf2+j, ColCount[j], XBar, V, S]); - end; + lReport.Add('TOTAL %3d %8.3f %8.3f %8.3f', [N, MeanDep, MSDep, sqrt(MSDep)]); - //Display means, variances and standard deviations for slices - for k := 0 to NoGrpsC - 1 do - begin - XBar := SlcSums[k] / SlcCount[k]; - OrdMeansC[k] := XBar; - SlcSS := 0.0; - for i := 0 to NoGrpsA - 1 do - for j := 0 to NoGrpsB - 1 do - SlcSS := SlcSS + wx2[i,j,k]; - V := SlcSS - (SlcSums[k] * SlcSums[k] / SlcCount[k]); - V := V / (SlcCount[k] - 1.0); - S := sqrt(V); - AReport.Add('Slice %3d %3d %8.3f %8.3f %8.3f', [minf3+k, SlcCount[k], XBar, V, S]); - end; + FReportFrame.DisplayReport(lReport); - AReport.Add('TOTAL %3d %8.3f %8.3f %8.3f', [N, MeanDep, MSDep, sqrt(MSDep)]); - AReport.Add(''); - AReport.Add(''); + finally + lReport.Free; + end; end; +{ Determines from the ItemIndex of the FChartCombobox which factors will be + plotted along x and as y index, and for which C index the interactions will + be calculated. } procedure TOneCaseAnovaform.GetDataIndices(out ix, iy, iz: Integer); var index, i1, i2, i3: Integer; @@ -1473,6 +1227,8 @@ begin end; +{ OnChange event handler for the ChartCombobox. Displays the chart associated + with the current ItemIndex. } procedure TOneCaseAnovaForm.SelectThreeWayPlot(Sender: TObject); var i, j, k, idx, ix, iy, iz: Integer; @@ -1486,21 +1242,21 @@ begin FSeries.ListSource.YCount := 1; for i := 0 to NF1Cells-1 do FSeries.AddXY(minF1 + i, RowSums[i] / RowCount[i], IntToStr(MinF1 + i)); - FChartFrame.SetXTitle(Factor1Edit.Text); + FChartFrame.SetXTitle(Factor1Edit.Text + ' codes'); FChartFrame.SetTitle(Factor1Edit.Text); end; 1: begin // Plot means vs factor B FSeries.ListSource.YCount := 1; for j := 0 to NF2Cells-1 do FSeries.AddXY(minF2 + j, ColSums[j] / ColCount[j], IntToStr(MinF2 + j)); - FChartFrame.SetXTitle(Factor2Edit.Text); + FChartFrame.SetXTitle(Factor2Edit.Text + ' codes'); FChartFrame.SetTitle(Factor2Edit.Text); end; 2: begin // Plot means vs factor C FSeries.ListSource.YCount := 1; for i := 0 to NF3Cells-1 do FSeries.AddXY(minF3 + i, SlcSums[i] / SlcCount[i], IntToStr(MinF3 + i)); - FChartFrame.SetXTitle(Factor3Edit.Text); + FChartFrame.SetXTitle(Factor3Edit.Text + ' codes'); FChartFrame.SetTitle(Factor3Edit.Text); end; else @@ -1656,704 +1412,543 @@ end; procedure TOneCaseAnovaForm.ThreeWayPlot; -var - clr: TColor; begin - if FChartComboBox.ItemIndex = -1 then - clr := DATA_COLORS[0] - else - clr := DATA_COLORS[FChartComboBox.ItemIndex mod Length(DATA_COLORS)]; + if not ShowPlotsChk.Checked then + begin + ChartPage.TabVisible := false; + exit; + end; + FChartFrame.Clear; // this destroys the series FChartFrame.SetYTitle('Means'); - FSeries := FChartFrame.PlotXY(ptBars, nil, nil, nil, nil, '', clr); - TBarSeries(FSeries).Stacked := false; + FSeries := FChartFrame.PlotXY(ptBars, nil, nil, nil, nil, '', DATA_Colors[0]); + with TBarSeries(FSeries) do + begin + Stacked := false; + {$IF LCL_FullVersion >= 2010000} + DepthBrightnessDelta := -30; + {$IFEND} + end; + if Plot3DChk.Checked then + FSeries.Depth := 20; PopulateChartCombobox(true); FChartCombobox.OnChange := @SelectThreeWayPlot; SelectThreeWayPlot(nil); + + ChartPage.TabVisible := true; end; -(* -procedure TOneCaseAnovaForm.ThreeWayPlot; + +procedure TOneCaseAnovaForm.TwoWayContrasts; var - i, j, k: integer; - maxmean, XBar: double; - XValue: DblDyneVec = nil; - plottype: integer; -begin - if CompError then - exit; - - case PlotOptionsGroup.ItemIndex of - 0: exit; - 1: plotType := 2; // 3D bars - 2: plotType := 1; // 2D bars - 3: plotType := 9; // 2D horizontal bars - else raise Exception.Create('Plot type not supported.'); - end; - - SetLength(XValue, TotalCells); - - // Factor A first - GraphFrm.SetLabels[1] := 'FACTOR A'; - maxmean := 0.0; - SetLength(GraphFrm.Xpoints, 1, Nf1cells); - SetLength(GraphFrm.Ypoints, 1, Nf1cells); - for i := 0 to Nf1cells - 1 do - begin - RowSums[i] := RowSums[i] / RowCount[i]; - GraphFrm.Ypoints[0,i] := RowSums[i]; - if (RowSums[i] > maxmean) then maxmean := RowSums[i]; - XValue[i] := minf1 + i; - GraphFrm.Xpoints[0,i] := XValue[i]; - end; - GraphFrm.nosets := 1; - GraphFrm.nbars := Nf1cells; - GraphFrm.Heading := Factor1Edit.Text; - GraphFrm.XTitle := Factor1Edit.Text + ' Codes'; - GraphFrm.YTitle := 'Mean'; - GraphFrm.barwideprop := 0.5; - GraphFrm.AutoScaled := false; - GraphFrm.miny := 0.0; - GraphFrm.maxy := maxmean; - GraphFrm.GraphType := plottype; - GraphFrm.BackColor := clCream; - GraphFrm.WallColor := clDkGray; - GraphFrm.FloorColor := clLtGray; - GraphFrm.ShowBackWall := true; - GraphFrm.ShowModal; - GraphFrm.Xpoints := nil; - GraphFrm.Ypoints := nil; - - // Factor B next - GraphFrm.SetLabels[1] := 'FACTOR B'; - maxmean := 0.0; - SetLength(GraphFrm.Xpoints, 1, Nf2cells); - SetLength(GraphFrm.Ypoints, 1, Nf2cells); - for i := 0 to Nf2cells - 1 do - begin - ColSums[i] := ColSums[i] / ColCount[i]; - GraphFrm.Ypoints[0,i] := ColSums[i]; - if (ColSums[i] > maxmean) then maxmean := ColSums[i]; - XValue[i] := minf2 + i; - GraphFrm.Xpoints[0,i] := XValue[i]; - end; - GraphFrm.nosets := 1; - GraphFrm.nbars := Nf2cells; - GraphFrm.Heading := Factor2Edit.Text; - GraphFrm.XTitle := Factor2Edit.Text + ' Codes'; - GraphFrm.YTitle := 'Mean'; - GraphFrm.barwideprop := 0.5; - GraphFrm.AutoScaled := false; - GraphFrm.miny := 0.0; - GraphFrm.maxy := maxmean; - GraphFrm.GraphType := plottype; - GraphFrm.BackColor := clCream; - GraphFrm.WallColor := clDkGray; - GraphFrm.FloorColor := clLtGray; - GraphFrm.ShowBackWall := true; - GraphFrm.ShowModal; - GraphFrm.Xpoints := nil; - GraphFrm.Ypoints := nil; - - // Factor C next - GraphFrm.SetLabels[1] := 'FACTOR C'; - maxmean := 0.0; - SetLength(GraphFrm.Xpoints, 1, Nf3cells); - SetLength(GraphFrm.Ypoints, 1, Nf3cells); - for i := 0 to Nf3cells - 1 do - begin - SlcSums[i] := SlcSums[i] / SlcCount[i]; - GraphFrm.Ypoints[0,i] := SlcSums[i]; - if (SlcSums[i] > maxmean) then maxmean := SlcSums[i]; - XValue[i] := minf3 + i; - GraphFrm.Xpoints[0,i] := XValue[i]; - end; - GraphFrm.nosets := 1; - GraphFrm.nbars := Nf3cells; - GraphFrm.Heading := Factor3Edit.Text; - GraphFrm.XTitle := Factor2Edit.Text + ' Codes'; // why not Factor3? - GraphFrm.YTitle := 'Mean'; - GraphFrm.barwideprop := 0.5; - GraphFrm.AutoScaled := false; - GraphFrm.miny := 0.0; - GraphFrm.maxy := maxmean; - GraphFrm.GraphType := plottype; - GraphFrm.BackColor := clCream; - GraphFrm.WallColor := clDkGray; - GraphFrm.FloorColor := clLtGray; - GraphFrm.ShowBackWall := true; - GraphFrm.ShowModal; - GraphFrm.Xpoints := nil; - GraphFrm.Ypoints := nil; - - // Factor A x B Interaction within each slice next - SetLength(GraphFrm.Ypoints, Nf1cells, Nf2cells); - SetLength(GraphFrm.Xpoints, 1, Nf2cells); - for k := 0 to Nf3cells - 1 do - begin - maxmean := 0.0; - for i := 0 to Nf1cells - 1 do - begin - GraphFrm.SetLabels[i+1] := Factor1Edit.Text + ' ' + IntToStr(i+1); - for j := 0 to Nf2cells - 1 do - begin - XBar := wsum[i,j,k] / ncnt[i,j,k]; - if (XBar > maxmean) then maxmean := XBar; - GraphFrm.Ypoints[i,j] := XBar; - end; - end; - for j := 0 to Nf2cells - 1 do - begin - XValue[j] := minf2 + j ; - GraphFrm.Xpoints[0,j] := XValue[j]; - end; - - GraphFrm.nosets := Nf1cells; - GraphFrm.nbars := Nf2cells; - GraphFrm.Heading := 'Factor A x Factor B Within C ' + IntToStr(k+1); - GraphFrm.XTitle := Factor2Edit.Text + ' Codes'; - GraphFrm.YTitle := 'Mean'; - GraphFrm.barwideprop := 0.2; - GraphFrm.AutoScaled := false; - GraphFrm.miny := 0.0; - GraphFrm.maxy := maxmean; - GraphFrm.GraphType := plottype; - GraphFrm.BackColor := clCream; - GraphFrm.WallColor := clDkGray; - GraphFrm.FloorColor := clLtGray; - GraphFrm.ShowBackWall := true; - GraphFrm.ShowModal; - end; - GraphFrm.Xpoints := nil; - GraphFrm.Ypoints := nil; - - // Factor A x C Interaction within each Column next - SetLength(GraphFrm.Xpoints, 1, Nf3cells); - SetLength(GraphFrm.Ypoints, Nf1cells, Nf3cells); - for j := 0 to Nf2cells - 1 do - begin - maxmean := 0.0; - for i := 0 to Nf1cells - 1 do - begin - GraphFrm.SetLabels[i+1] := Factor1Edit.Text + ' ' + IntToStr(i+1); - for k := 0 to Nf3cells - 1 do - begin - XBar := wsum[i,j,k] / ncnt[i,j,k]; - if (XBar > maxmean) then maxmean := XBar; - GraphFrm.Ypoints[i,k] := XBar; - end; - end; - for k := 0 to Nf3cells - 1 do - begin - XValue[k] := minf3 + k; - GraphFrm.Xpoints[0,k] := XValue[k]; - end; - - GraphFrm.nosets := Nf1cells; - GraphFrm.nbars := Nf3cells; - GraphFrm.Heading := 'Factor A x Factor C Within B ' + IntToStr(j+1); - GraphFrm.XTitle := Factor3Edit.Text + ' Codes'; - GraphFrm.YTitle := 'Mean'; - GraphFrm.barwideprop := 0.2; - GraphFrm.AutoScaled := false; - GraphFrm.miny := 0.0; - GraphFrm.maxy := maxmean; - GraphFrm.GraphType := plottype; - GraphFrm.BackColor := clCream; - GraphFrm.WallColor := clDkGray; - GraphFrm.FloorColor := clLtGray; - GraphFrm.ShowBackWall := true; - GraphFrm.ShowModal; - end; - GraphFrm.Xpoints := nil; - GraphFrm.Ypoints := nil; - - // Factor B x C Interaction within each row next - SetLength(GraphFrm.Xpoints, 1, Nf3cells); - SetLength(GraphFrm.Ypoints, Nf2cells, Nf3cells); - for i := 0 to Nf1cells - 1 do - begin - maxmean := 0.0; - for j := 0 to Nf2cells - 1 do - begin - GraphFrm.SetLabels[j+1] := Factor2Edit.Text + ' ' + IntToStr(j+1); - for k := 0 to Nf3cells - 1 do - begin - XBar := wsum[i,j,k] / ncnt[i,j,k]; - if (XBar > maxmean) then maxmean := XBar; - GraphFrm.Ypoints[j,k] := XBar; - end; - end; - for j := 0 to Nf3cells - 1 do - begin - XValue[j] := minf3 + j; - GraphFrm.Xpoints[0,j] := XValue[j]; - end; - - GraphFrm.nosets := Nf2cells; - GraphFrm.nbars := Nf3cells; - GraphFrm.Heading := 'Factor B x Factor C Within A ' + IntToStr(i+1); - GraphFrm.XTitle := Factor3Edit.Text + ' Codes'; - GraphFrm.YTitle := 'Mean'; - GraphFrm.barwideprop := 0.2; - GraphFrm.AutoScaled := false; - GraphFrm.miny := 0.0; - GraphFrm.maxy := maxmean; - GraphFrm.GraphType := plottype; - GraphFrm.BackColor := clCream; - GraphFrm.WallColor := clDkGray; - GraphFrm.FloorColor := clLtGray; - GraphFrm.ShowBackWall := true; - GraphFrm.ShowModal; - end; // next row - GraphFrm.Xpoints := nil; - GraphFrm.Ypoints := nil; - XValue := nil; -end; -*) - - -procedure TOneCaseAnovaForm.TwoWayContrasts(AReport: TStrings); -var - i, j: integer; - value, alpha: double; - variances: DblDyneVec = nil; + lReport: TStrings; + i, j, totalCells: integer; + value, alpha, posthocAlpha: double; + cellCnts: IntDyneVec = nil; + cellVars: DblDyneVec = nil; + cellSums: DblDyneVec = nil; RowSS, ColSS: double; -begin - if not comparisons then - exit; - if CompError then - exit; - - SetLength(variances, TotalCells); - alpha := StrToFloat(PostAlphaEdit.Text); - - // row comparisons - if (Nf1cells > 2) and (ProbF1 < Overall) then - begin - for i := 0 to NoGrpsA - 1 do - begin - RowSS := 0.0; - for j := 0 to NoGrpsB - 1 do RowSS := RowSS + vars[i,j]; - variances[i] := RowSS - sqr(RowSums[i]) / RowCount[i]; - variances[i] := variances[i] / (RowCount[i] - 1.0); - end; - - AReport.Add(''); - AReport.Add('COMPARISONS AMONG ROWS'); - - // get smallest group size - value := 1e308; - for i := 0 to Nf1cells - 1 do - if (RowCount[i] < value) then value := RowCount[i]; - - if ScheffeChk.Checked then - ScheffeTest(MSErr, RowSums, RowCount, minf1, maxf1, N, posthocAlpha, AReport); - if TukeyHSDChk.Checked and equal_grp then - Tukey(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, AReport); - if TukeyBChk.Checked and equal_grp then - TukeyBTest(MSErr, DFErr, RowSums, RowCount, minf1, maxf1, value, posthocAlpha, AReport); - if TukeyKramerChk.Checked and equal_grp then - Tukey_Kramer(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, AReport); -// if (BonferroniChk.Checked) then -// Bonferroni(RowSums,RowCount,variances,minf1,maxf1, AReport); -// if (OrthogonalChk.Checked) then -// CONTRASTS(MSErr,DFErr,RowSums,RowCount,minf1,maxf1,Alpha, AReport); - if NewmanKeulsChk.Checked and equal_grp then - Newman_Keuls(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, AReport); - end; - - // column comparisons - if (Nf2cells > 2) and (ProbF2 < Alpha) then - begin - for j := 0 to NoGrpsB - 1 do - begin - ColSS := 0.0; - for i := 0 to NoGrpsA - 1 do ColSS := ColSS + vars[i,j]; - variances[j] := ColSS - (ColSums[j] * ColSums[j] / ColCount[j]); - variances[j] := variances[j] / (ColCount[j] - 1.0); - end; - AReport.Add(''); - AReport.Add('COMPARISONS AMONG COLUMNS'); - value := 1e308; - for i := 0 to Nf2cells - 1 do - if (ColCount[i] < value) then value := ColCount[i]; - - if ScheffeChk.Checked then - ScheffeTest(MSErr, ColSums, ColCount, minf2, maxf2, N, posthocAlpha, AReport); - if TukeyHSDChk.Checked and equal_grp then - Tukey(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, AReport); - if TukeyBChk.Checked and equal_grp then - TukeyBTest(MSErr, DFErr, ColSums, ColCount, minf2, maxf2, value, posthocAlpha, AReport); - if TukeyKramerChk.Checked and equal_grp then - Tukey_Kramer(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, AReport); -// if (BonferroniChk.Checked) then -// Bonferroni(ColSums,ColCount,variances,minf2,maxf2, AReport); -// if (OrthogonalChk.Checked) then -// CONTRASTS(MSErr,DFErr,ColSums,ColCount,minf2,maxf2,Alpha, AReport); - if NewmanKeulsChk.Checked and equal_grp then - Newman_Keuls(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, AReport); - end; - - // simple effects for columns within each row - if (ProbF3 < Alpha) then - begin - AReport.Add(''); - AReport.Add('COMPARISONS AMONG COLUMNS WITHIN EACH ROW'); - for i := 0 to Nf1cells - 1 do - begin - AReport.Add(''); - AReport.Add('ROW %d COMPARISONS', [i+1]); - // move cell sums and counts to cellsums and cellcnts - for j := 0 to Nf2cells - 1 do - begin - cellsums[j] := sums[i,j]; - cellcnts[j] := counts[i,j]; - cellvars[j] := vars[i,j]; - end; - value := 1e308; - for j := 0 to Nf2cells - 1 do - if (cellcnts[j] < value) then value := cellcnts[j]; - - if ScheffeChk.Checked then - ScheffeTest(MSErr, cellsums, cellcnts, minf2, maxf2, N, posthocAlpha, AReport); - if TukeyHSDChk.Checked and equal_grp then - Tukey(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, AReport); - if TukeyBChk.Checked and equal_grp then - TukeyBTest(MSErr, DFErr, cellsums, cellcnts, minf2, maxf2, value, posthocAlpha, AReport); - if TukeyKramerChk.Checked and equal_grp then - Tukey_Kramer(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, AReport); -// if (BonferroniChk.Checked) then -// Bonferroni(cellsums,cellcnts,cellvars,minf2,maxf2, AReport); -// if (OrthogonalChk.Checked) then -// CONTRASTS(MSErr,DFErr,cellsums,cellcnts,minf2,maxf2,0.05, AReport); - if NewmanKeulsChk.Checked and equal_grp then - Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, AReport); - end; - end; - - // simple effects for rows within each column - if (ProbF3 < Alpha) then - begin - AReport.Add(''); - AReport.Add('COMPARISONS AMONG ROWS WITHIN EACH COLUMN'); - for j := 0 to Nf2cells - 1 do - begin - AReport.Add(''); - AReport.Add('COLUMN %d COMPARISONS', [j+1]); - // move cell sums and counts to cellsums and cellcnts - for i := 0 to Nf1cells - 1 do - begin - cellsums[i] := sums[i,j]; - cellcnts[i] := counts[i,j]; - cellvars[i] := vars[i,j]; - end; - value := 1e308; - for i := 0 to Nf1cells - 1 do - if (cellcnts[j] < value) then value := cellcnts[j]; - - if ScheffeChk.Checked then - ScheffeTest(MSErr, cellsums, cellcnts, minf1, maxf1, N, posthocAlpha, AReport); - if TukeyHSDChk.Checked and equal_grp then - Tukey(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, AReport); - if TukeyBChk.Checked and equal_grp then - TukeyBTest(MSErr, DFErr, cellsums, cellcnts, minf1, maxf1, value, posthocAlpha, AReport); - if TukeyKramerChk.Checked and equal_grp then - Tukey_Kramer(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, AReport); -// if (BonferroniChk.Checked) then -// Bonferroni(cellsums,cellcnts,cellvars,minf1,maxf1, AReport); -// if (OrthogonalChk.Checked) then -// CONTRASTS(MSErr,DFErr,cellsums,cellcnts,minf1,maxf1,0.05, AReport); - if NewmanKeulsChk.Checked and equal_grp then - Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, AReport); - end; - end; - variances := nil; -end; - - -procedure TOneCaseAnovaForm.ThreeWayContrasts(AReport: TStrings); -var - i, j, k: integer; - value, alpha: double; variances: DblDyneVec = nil; - RowSS, ColSS, SlcSS: double; begin - if not comparisons then - exit; - if CompError then - exit; - - alpha := StrToFloat(PostAlphaEdit.Text); if not (ScheffeChk.Checked or TukeyHSDChk.Checked or TukeyBChk.Checked or - TukeyKramerChk.Checked or NewmanKeulsChk.Checked) then exit; - - SetLength(variances, TotalCells); - - // row comparisons - if (Nf1cells > 2) and (ProbF1 < Alpha) then + TukeyKramerChk.Checked or NewmanKeulsChk.Checked) then begin - for i := 0 to NoGrpsA - 1 do + PostHocPage.TabVisible := false; + exit; + end; + + totalCells := NF1Cells + NF2Cells + NF3Cells; + + // allocate space + SetLength(CellCnts, totalCells); // array of cell counts + SetLength(CellVars, totalCells); // arrray of cell sums of squares variances + SetLength(CellSums, totalCells); // array of cell sums means + SetLength(Variances, totalCells); + + alpha := StrToFloat(OverallAlphaEdit.Text); + postHocAlpha := StrToFloat(PostAlphaEdit.Text); + + lReport := TStringList.Create; + try + // row comparisons + if (Nf1cells > 2) and (ProbF1 < alpha) then + begin + for i := 0 to NoGrpsA - 1 do + begin + RowSS := 0.0; + for j := 0 to NoGrpsB - 1 do RowSS := RowSS + vars[i,j]; + variances[i] := RowSS - sqr(RowSums[i]) / RowCount[i]; + variances[i] := variances[i] / (RowCount[i] - 1.0); + end; + + if lReport.Count > 0 then + lReport.Add(''); + lReport.Add('COMPARISONS AMONG ROWS'); + + // get smallest group size + value := 1e308; + for i := 0 to Nf1cells - 1 do + if (RowCount[i] < value) then value := RowCount[i]; + + if ScheffeChk.Checked then + ScheffeTest(MSErr, RowSums, RowCount, minf1, maxf1, N, posthocAlpha, lReport); + if TukeyHSDChk.Checked and equal_grp then + Tukey(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, lReport); + if TukeyBChk.Checked and equal_grp then + TukeyBTest(MSErr, DFErr, RowSums, RowCount, minf1, maxf1, value, posthocAlpha, lReport); + if TukeyKramerChk.Checked and equal_grp then + Tukey_Kramer(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, lReport); + // if (BonferroniChk.Checked) then + // Bonferroni(RowSums,RowCount,variances,minf1,maxf1, lReport); + // if (OrthogonalChk.Checked) then + // CONTRASTS(MSErr,DFErr,RowSums,RowCount,minf1,maxf1,Alpha, lReport); + if NewmanKeulsChk.Checked and equal_grp then + Newman_Keuls(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, lReport); + end; + + // column comparisons + if (Nf2cells > 2) and (ProbF2 < alpha) then begin - RowSS := 0.0; for j := 0 to NoGrpsB - 1 do - for k := 0 to NoGrpsC - 1 do - RowSS := RowSS + wx2[i,j,k]; - variances[i] := RowSS - sqr(RowSums[i]) / RowCount[i]; - variances[i] := variances[i] / (RowCount[i] - 1.0); - end; - AReport.Add(''); - AReport.Add('COMPARISONS AMONG ROWS'); - - // get smallest group size - value := 1e308; - for i := 0 to Nf1cells - 1 do - if (RowCount[i] < value) then value := RowCount[i]; - - if ScheffeChk.Checked then - ScheffeTest(MSErr, RowSums, RowCount, minf1, maxf1, N, posthocAlpha, AReport); - if TukeyHSDChk.Checked and equal_grp then - Tukey(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, AReport); - if TukeyBChk.Checked and equal_grp then - TukeyBTest(MSErr, DFErr, RowSums, RowCount, minf1, maxf1, value, posthocAlpha, AReport); - if TukeyKramerChk.Checked and equal_grp then - Tukey_Kramer(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, AReport); -// if (BonferroniChk.Checked) then -// Bonferroni(RowSums,RowCount,variances,minf1,maxf1, AReport); -// if (OrthogonalChk.Checked) then -// CONTRASTS(MSErr,DFErr,RowSums,RowCount,minf1,maxf1,Alpha, AReport); - if NewmanKeulsChk.Checked and equal_grp then - Newman_Keuls(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, AReport); - end; - - // column comparisons - if (Nf2cells > 2) and (ProbF2 < Alpha) then - begin - for j := 0 to NoGrpsB - 1 do - begin - ColSS := 0.0; - for i := 0 to NoGrpsA - 1 do - for k := 0 to NoGrpsC - 1 do - ColSS := ColSS + wx2[i,j,k]; - variances[j] := ColSS - sqr(ColSums[j]) / ColCount[j]; - variances[j] := variances[j] / (ColCount[j] - 1.0); - end; - AReport.Add(''); - AReport.Add('COMPARISONS AMONG COLUMNS'); - value := 1e308; - for i := 0 to Nf2cells - 1 do - if (ColCount[i] < value) then value := ColCount[i]; - - if ScheffeChk.Checked then - ScheffeTest(MSErr, ColSums, ColCount, minf2, maxf2, N, posthocAlpha, AReport); - if TukeyHSDChk.Checked and equal_grp then - Tukey(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, AReport); - if TukeyBChk.Checked and equal_grp then - TukeyBTest(MSErr, DFErr, ColSums, ColCount, minf2, maxf2, value, posthocAlpha, AReport); - if TukeyKramerChk.Checked and equal_grp then - Tukey_Kramer(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, AReport); -// if (BonferroniChk.Checked) then -// Bonferroni(ColSums,ColCount,variances,minf2,maxf2, AReport); -// if (OrthogonalChk.Checked) then -// CONTRASTS(MSErr,DFErr,ColSums,ColCount,minf2,maxf2,Alpha, AReport); - if NewmanKeulsChk.Checked and equal_grp then - Newman_Keuls(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, AReport); - end; - - // slice comparisons - if (Nf3cells > 2) and (ProbF3 < Alpha) then - begin - for k := 0 to NoGrpsC - 1 do - begin - SlcSS := 0.0; - for i := 0 to NoGrpsA - 1 do - for j := 0 to NoGrpsB - 1 do SlcSS := SlcSS + wx2[i,j,k]; - variances[k] := SlcSS - sqr(SlcSums[k]) / SlcCount[k]; - variances[k] := variances[k] / (SlcCount[k] - 1.0); - end; - AReport.Add(''); - AReport.Add('COMPARISONS AMONG SLICES'); - value := 1e308; - for i := 0 to Nf3cells - 1 do - if (SlcCount[i] < value) then value := SlcCount[i]; - - if ScheffeChk.Checked then - ScheffeTest(MSErr, SlcSums, SlcCount, minf3, maxf3, N, posthocAlpha, AReport); - if TukeyHSDChk.Checked and equal_grp then - Tukey(MSErr, DFErr, value, SlcSums, SlcCount, minf3, maxf3, posthocAlpha, AReport); - if TukeyBChk.Checked and equal_grp then - TukeyBTest(MSErr, DFErr, SlcSums, SlcCount, minf3, maxf3, value, posthocAlpha, AReport); - if TukeyKramerChk.Checked and equal_grp then - Tukey_Kramer(MSErr, DFErr, value, SlcSums, SlcCount, minf3, maxf3, posthocAlpha, AReport); -// if (BonferroniChk.Checked) then -// Bonferroni(SlcSums,SlcCount,variances,minf3,maxf3, AReport); -// if (OrthogonalChk.Checked) then -// CONTRASTS(MSErr,DFErr,SlcSums,SlcCount,minf3,maxf3,Alpha, AReport); - if NewmanKeulsChk.Checked and equal_grp then - Newman_Keuls(MSErr, DFErr, value, SlcSums, SlcCount, minf3, maxf3, posthocAlpha, AReport); - end; - - // simple effects for columns within each row - if (ProbF1F2 < Alpha) then - begin - AReport.Add(''); - AReport.Add('COMPARISONS AMONG COLUMNS WITHIN EACH ROW'); - for i := 0 to Nf1cells - 1 do - begin - AReport.Add(''); - AReport.Add('ROW %d COMPARISONS', [i+1]); - // move cell sums && counts to cellsums && cellcnts - for j := 0 to Nf2cells - 1 do begin - for k := 0 to Nf3cells - 1 do - begin - cellsums[j] := wsum[i,j,k]; - cellcnts[j] := ncnt[i,j,k]; - cellvars[j] := wx2[i,j,k]; - end; + ColSS := 0.0; + for i := 0 to NoGrpsA - 1 do ColSS := ColSS + vars[i,j]; + variances[j] := ColSS - (ColSums[j] * ColSums[j] / ColCount[j]); + variances[j] := variances[j] / (ColCount[j] - 1.0); end; + if lReport.Count > 0 then + lReport.Add(''); + lReport.Add('COMPARISONS AMONG COLUMNS'); value := 1e308; - for j := 0 to Nf2cells - 1 do - if (cellcnts[j] < value) then value := cellcnts[j]; + for i := 0 to Nf2cells - 1 do + if (ColCount[i] < value) then value := ColCount[i]; if ScheffeChk.Checked then - ScheffeTest(MSErr, cellsums, cellcnts, minf2, maxf2, N, posthocAlpha, AReport); + ScheffeTest(MSErr, ColSums, ColCount, minf2, maxf2, N, posthocAlpha, lReport); if TukeyHSDChk.Checked and equal_grp then - Tukey(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, AReport); + Tukey(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, lReport); if TukeyBChk.Checked and equal_grp then - TukeyBTest(MSErr, DFErr, cellsums, cellcnts, minf2, maxf2, value, posthocAlpha, AReport); + TukeyBTest(MSErr, DFErr, ColSums, ColCount, minf2, maxf2, value, posthocAlpha, lReport); if TukeyKramerChk.Checked and equal_grp then - Tukey_Kramer(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, AReport); -// if (BonferroniChk.Checked) then -// Bonferroni(cellsums,cellcnts,cellvars,minf2,maxf2, AReport); -// if (OrthogonalChk.Checked) then -// CONTRASTS(MSErr,DFErr,cellsums,cellcnts,minf2,maxf2,0.05, AReport); + Tukey_Kramer(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, lReport); + // if (BonferroniChk.Checked) then + // Bonferroni(ColSums,ColCount,variances,minf2,maxf2, lReport); + // if (OrthogonalChk.Checked) then + // CONTRASTS(MSErr,DFErr,ColSums,ColCount,minf2,maxf2,Alpha, lReport); if NewmanKeulsChk.Checked and equal_grp then - Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, AReport); + Newman_Keuls(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, lReport); end; - end; - // simple effects for rows within each column - if (ProbF1F2 < Alpha) then - begin - AReport.Add(''); - AReport.Add('COMPARISONS AMONG ROWS WITHIN EACH COLUMN'); - for j := 0 to Nf2cells - 1 do + // simple effects for columns within each row + if (ProbF3 < alpha) then begin - AReport.Add(''); - AReport.Add('COLUMN %d COMPARISONS', [j+1]); - // move cell sums && counts to cellsums && cellcnts - for i := 0 to Nf1cells - 1 do - begin - for k := 0 to Nf3cells - 1 do - begin - cellsums[i] := wsum[i,j,k]; - cellcnts[i] := ncnt[i,j,k]; - cellvars[i] := wx2[i,j,k]; - end; - end; - value := 1e308; - for i := 0 to Nf1cells - 1 do - if (cellcnts[j] < value) then value := cellcnts[j]; - - if ScheffeChk.Checked then - ScheffeTest(MSErr, cellsums, cellcnts, minf1, maxf1, N, posthocAlpha, AReport); - if TukeyHSDChk.Checked and equal_grp then - Tukey(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, AReport); - if TukeyBChk.Checked and equal_grp then - TukeyBTest(MSErr, DFErr, cellsums, cellcnts, minf1, maxf1, value, posthocAlpha, AReport); - if TukeyKramerChk.Checked and equal_grp then - Tukey_Kramer(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, AReport); -// if (BonferroniChk.Checked) then -// Bonferroni(cellsums,cellcnts,cellvars,minf1,maxf1, AReport); -// if (OrthogonalChk.Checked) then -// CONTRASTS(MSErr,DFErr,cellsums,cellcnts,minf1,maxf1,0.05, AReport); - if NewmanKeulsChk.Checked and equal_grp then - Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, AReport); - end; - end; - - // simple effects for columns within each slice - if (ProbF2F3 < Alpha) then - begin - AReport.Add(''); - AReport.Add('COMPARISONS AMONG COLUMNS WITHIN EACH SLICE'); - for k := 0 to Nf3cells - 1 do - begin - AReport.Add(''); - AReport.Add('SLICE %d COMPARISONS', [k+1]); - // move cell sums && counts to cellsums && cellcnts - for j := 0 to Nf2cells - 1 do - begin - for i := 0 to Nf1cells - 1 do - begin - cellsums[j] := wsum[i,j,k]; - cellcnts[j] := ncnt[i,j,k]; - cellvars[j] := wx2[i,j,k]; - end; - end; - value := 1e308; - for j := 0 to Nf2cells-1 do - if (cellcnts[j] < value) then value := cellcnts[j]; - - if ScheffeChk.Checked then - ScheffeTest(MSErr, cellsums, cellcnts, minf2, maxf2, N, posthocAlpha, AReport); - if TukeyHSDChk.Checked and equal_grp then - Tukey(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, AReport); - if TukeyBChk.Checked and equal_grp then - TukeyBTest(MSErr, DFErr, cellsums, cellcnts, minf2, maxf2, value, posthocAlpha, AReport); - if TukeyKramerChk.Checked and equal_grp then - Tukey_Kramer(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, AReport); -// if (BonferroniChk.Checked) then -// Bonferroni(cellsums, cellcnts, cellvars, minf2, maxf2, posthocAlpha, AReport); -// if (OrthogonalChk.Checked) then -// CONTRASTS(MSErr, DFErr, cellsums, cellcnts, minf2, maxf2, posthocAlpha, AReport); - if NewmanKeulsChk.Checked and equal_grp then - Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, AReport); - end; - end; - - // simple effects for rows within each slice - if (ProbF1F3 < Alpha) then - begin - AReport.Add(''); - AReport.Add('COMPARISONS AMONG ROWS WITHIN EACH SLICE'); - for k := 0 to Nf3cells - 1 do - begin - AReport.Add(''); - AReport.Add('SLICE %d COMPARISONS', [k+1]); - // move cell sums && counts to cellsums && cellcnts + if lReport.Count > 0 then + lReport.Add(''); + lReport.Add('COMPARISONS AMONG COLUMNS WITHIN EACH ROW'); for i := 0 to Nf1cells - 1 do begin + lReport.Add(''); + lReport.Add('ROW %d COMPARISONS', [i+1]); + // move cell sums and counts to cellsums and cellcnts for j := 0 to Nf2cells - 1 do begin - cellsums[j] := wsum[i,j,k]; - cellcnts[j] := ncnt[i,j,k]; - cellvars[j] := wx2[i,j,k]; + cellsums[j] := sums[i,j]; + cellcnts[j] := counts[i,j]; + cellvars[j] := vars[i,j]; end; - end; - value := 1e308; - for i := 0 to Nf1cells - 1 do - if (cellcnts[i] < value) then value := cellcnts[i]; + value := 1e308; + for j := 0 to Nf2cells - 1 do + if (cellcnts[j] < value) then value := cellcnts[j]; - if ScheffeChk.Checked then - ScheffeTest(MSErr, cellsums, cellcnts, minf1, maxf1, N, posthocAlpha, AReport); - if TukeyHSDChk.Checked and equal_grp then - Tukey(MSErr,DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, AReport); - if TukeyBChk.Checked and equal_grp then - TukeyBTest(MSErr, DFErr, cellsums, cellcnts, minf1, maxf1, value, posthocAlpha, AReport); - if TukeyKramerChk.Checked and equal_grp then - Tukey_Kramer(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, AReport); -// if (BonferroniChk.Checked) then -// Bonferroni(cellsums,cellcnts,cellvars,minf1,maxf1, posthocAlpha, AReport); -// if (OrthogonalChk.Checked) then -// CONTRASTS(MSErr,DFErr,cellsums,cellcnts,minf1,maxf1,posthocAlpha, AReport); - if NewmanKeulsChk.Checked and equal_grp then - Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, AReport); + if ScheffeChk.Checked then + ScheffeTest(MSErr, cellsums, cellcnts, minf2, maxf2, N, posthocAlpha, lReport); + if TukeyHSDChk.Checked and equal_grp then + Tukey(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, lReport); + if TukeyBChk.Checked and equal_grp then + TukeyBTest(MSErr, DFErr, cellsums, cellcnts, minf2, maxf2, value, posthocAlpha, lReport); + if TukeyKramerChk.Checked and equal_grp then + Tukey_Kramer(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, lReport); + // if (BonferroniChk.Checked) then + // Bonferroni(cellsums,cellcnts,cellvars,minf2,maxf2, lReport); + // if (OrthogonalChk.Checked) then + // CONTRASTS(MSErr,DFErr,cellsums,cellcnts,minf2,maxf2,0.05, lReport); + if NewmanKeulsChk.Checked and equal_grp then + Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, lReport); + end; end; + + // simple effects for rows within each column + if (ProbF3 < alpha) then + begin + if lReport.Count > 0 then + lReport.Add(''); + lReport.Add('COMPARISONS AMONG ROWS WITHIN EACH COLUMN'); + for j := 0 to Nf2cells - 1 do + begin + lReport.Add(''); + lReport.Add('COLUMN %d COMPARISONS', [j+1]); + // move cell sums and counts to cellsums and cellcnts + for i := 0 to Nf1cells - 1 do + begin + cellsums[i] := sums[i,j]; + cellcnts[i] := counts[i,j]; + cellvars[i] := vars[i,j]; + end; + value := 1e308; + for i := 0 to Nf1cells - 1 do + if (cellcnts[j] < value) then value := cellcnts[j]; + + if ScheffeChk.Checked then + ScheffeTest(MSErr, cellsums, cellcnts, minf1, maxf1, N, posthocAlpha, lReport); + if TukeyHSDChk.Checked and equal_grp then + Tukey(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, lReport); + if TukeyBChk.Checked and equal_grp then + TukeyBTest(MSErr, DFErr, cellsums, cellcnts, minf1, maxf1, value, posthocAlpha, lReport); + if TukeyKramerChk.Checked and equal_grp then + Tukey_Kramer(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, lReport); + // if (BonferroniChk.Checked) then + // Bonferroni(cellsums,cellcnts,cellvars,minf1,maxf1, lReport); + // if (OrthogonalChk.Checked) then + // CONTRASTS(MSErr,DFErr,cellsums,cellcnts,minf1,maxf1,0.05, lReport); + if NewmanKeulsChk.Checked and equal_grp then + Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, lReport); + end; + end; + + FPostHocReportFrame.DisplayReport(lReport); + PosthocPage.TabVisible := true; + + finally + lReport.Clear; + end; +end; + + +procedure TOneCaseAnovaForm.ThreeWayContrasts; +var + lReport: TStrings; + i, j, k, totalCells: integer; + value, alpha, posthocAlpha: double; + RowSS, ColSS, SlcSS: double; + cellCnts: IntDyneVec = nil; + cellVars: DblDyneVec = nil; + cellSums: DblDyneVec = nil; + variances: DblDyneVec = nil; +begin + if not (ScheffeChk.Checked or TukeyHSDChk.Checked or TukeyBChk.Checked or + TukeyKramerChk.Checked or NewmanKeulsChk.Checked) then + begin + PosthocPage.TabVisible := false; + exit; end; - variances := nil; + alpha := StrToFloat(OverallAlphaEdit.Text); + posthocAlpha := StrToFloat(PostAlphaEdit.Text); + totalCells := NF1Cells + NF2Cells + NF3Cells; + + // allocate space + SetLength(cellCnts, totalCells); // array of cell counts + SetLength(cellVars, totalCells); // arrray of cell sums of squares variances + SetLength(cellSums, totalCells); // array of cell sums means + SetLength(variances, totalCells); + + lReport := TStringList.Create; + try + // row comparisons + if (NF1cells > 2) and (ProbF1 < alpha) then + begin + for i := 0 to NoGrpsA - 1 do + begin + RowSS := 0.0; + for j := 0 to NoGrpsB - 1 do + for k := 0 to NoGrpsC - 1 do + RowSS := RowSS + wx2[i,j,k]; + variances[i] := RowSS - sqr(RowSums[i]) / RowCount[i]; + variances[i] := variances[i] / (RowCount[i] - 1); + end; + + if lReport.Count > 0 then + lReport.Add(''); + lReport.Add('COMPARISONS AMONG ROWS'); + + // get smallest group size + value := 1e308; + for i := 0 to Nf1cells - 1 do + if (RowCount[i] < value) then value := RowCount[i]; + + if ScheffeChk.Checked then + ScheffeTest(MSErr, RowSums, RowCount, minf1, maxf1, N, posthocAlpha, lReport); + if TukeyHSDChk.Checked and equal_grp then + Tukey(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, lReport); + if TukeyBChk.Checked and equal_grp then + TukeyBTest(MSErr, DFErr, RowSums, RowCount, minf1, maxf1, value, posthocAlpha, lReport); + if TukeyKramerChk.Checked and equal_grp then + Tukey_Kramer(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, lReport); + // if (BonferroniChk.Checked) then + // Bonferroni(RowSums,RowCount,variances,minf1,maxf1, lReport); + // if (OrthogonalChk.Checked) then + // CONTRASTS(MSErr,DFErr,RowSums,RowCount,minf1,maxf1,Alpha, lReport); + if NewmanKeulsChk.Checked and equal_grp then + Newman_Keuls(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, lReport); + end; + + // column comparisons + if (Nf2cells > 2) and (ProbF2 < alpha) then + begin + for j := 0 to NoGrpsB - 1 do + begin + ColSS := 0.0; + for i := 0 to NoGrpsA - 1 do + for k := 0 to NoGrpsC - 1 do + ColSS := ColSS + wx2[i,j,k]; + variances[j] := ColSS - sqr(ColSums[j]) / ColCount[j]; + variances[j] := variances[j] / (ColCount[j] - 1.0); + end; + if lReport.Count > 0 then + lReport.Add(''); + lReport.Add('COMPARISONS AMONG COLUMNS'); + value := 1e308; + for i := 0 to Nf2cells - 1 do + if (ColCount[i] < value) then value := ColCount[i]; + + if ScheffeChk.Checked then + ScheffeTest(MSErr, ColSums, ColCount, minf2, maxf2, N, posthocAlpha, lReport); + if TukeyHSDChk.Checked and equal_grp then + Tukey(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, lReport); + if TukeyBChk.Checked and equal_grp then + TukeyBTest(MSErr, DFErr, ColSums, ColCount, minf2, maxf2, value, posthocAlpha, lReport); + if TukeyKramerChk.Checked and equal_grp then + Tukey_Kramer(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, lReport); + // if (BonferroniChk.Checked) then + // Bonferroni(ColSums,ColCount,variances,minf2,maxf2, lReport); + // if (OrthogonalChk.Checked) then + // CONTRASTS(MSErr,DFErr,ColSums,ColCount,minf2,maxf2,Alpha, lReport); + if NewmanKeulsChk.Checked and equal_grp then + Newman_Keuls(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, lReport); + end; + + // slice comparisons + if (Nf3cells > 2) and (ProbF3 < alpha) then + begin + for k := 0 to NoGrpsC - 1 do + begin + SlcSS := 0.0; + for i := 0 to NoGrpsA - 1 do + for j := 0 to NoGrpsB - 1 do SlcSS := SlcSS + wx2[i,j,k]; + variances[k] := SlcSS - sqr(SlcSums[k]) / SlcCount[k]; + variances[k] := variances[k] / (SlcCount[k] - 1.0); + end; + if lReport.Count > 0 then + lReport.Add(''); + lReport.Add('COMPARISONS AMONG SLICES'); + value := 1e308; + for i := 0 to Nf3cells - 1 do + if (SlcCount[i] < value) then value := SlcCount[i]; + + if ScheffeChk.Checked then + ScheffeTest(MSErr, SlcSums, SlcCount, minf3, maxf3, N, posthocAlpha, lReport); + if TukeyHSDChk.Checked and equal_grp then + Tukey(MSErr, DFErr, value, SlcSums, SlcCount, minf3, maxf3, posthocAlpha, lReport); + if TukeyBChk.Checked and equal_grp then + TukeyBTest(MSErr, DFErr, SlcSums, SlcCount, minf3, maxf3, value, posthocAlpha, lReport); + if TukeyKramerChk.Checked and equal_grp then + Tukey_Kramer(MSErr, DFErr, value, SlcSums, SlcCount, minf3, maxf3, posthocAlpha, lReport); + // if (BonferroniChk.Checked) then + // Bonferroni(SlcSums,SlcCount,variances,minf3,maxf3, lReport); + // if (OrthogonalChk.Checked) then + // CONTRASTS(MSErr,DFErr,SlcSums,SlcCount,minf3,maxf3,Alpha, lReport); + if NewmanKeulsChk.Checked and equal_grp then + Newman_Keuls(MSErr, DFErr, value, SlcSums, SlcCount, minf3, maxf3, posthocAlpha, lReport); + end; + + // simple effects for columns within each row + if (ProbF1F2 < alpha) then + begin + lReport.Add(''); + lReport.Add('COMPARISONS AMONG COLUMNS WITHIN EACH ROW'); + for i := 0 to Nf1cells - 1 do + begin + if lReport.Count > 0 then + lReport.Add(''); + lReport.Add('ROW %d COMPARISONS', [i+1]); + // move cell sums && counts to cellsums && cellcnts + for j := 0 to Nf2cells - 1 do + begin + for k := 0 to Nf3cells - 1 do + begin + cellsums[j] := wsum[i,j,k]; + cellcnts[j] := ncnt[i,j,k]; + cellvars[j] := wx2[i,j,k]; + end; + end; + value := 1e308; + for j := 0 to Nf2cells - 1 do + if (cellcnts[j] < value) then value := cellcnts[j]; + + if ScheffeChk.Checked then + ScheffeTest(MSErr, cellsums, cellcnts, minf2, maxf2, N, posthocAlpha, lReport); + if TukeyHSDChk.Checked and equal_grp then + Tukey(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, lReport); + if TukeyBChk.Checked and equal_grp then + TukeyBTest(MSErr, DFErr, cellsums, cellcnts, minf2, maxf2, value, posthocAlpha, lReport); + if TukeyKramerChk.Checked and equal_grp then + Tukey_Kramer(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, lReport); + // if (BonferroniChk.Checked) then + // Bonferroni(cellsums,cellcnts,cellvars,minf2,maxf2, lReport); + // if (OrthogonalChk.Checked) then + // CONTRASTS(MSErr,DFErr,cellsums,cellcnts,minf2,maxf2,0.05, lReport); + if NewmanKeulsChk.Checked and equal_grp then + Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, lReport); + end; + end; + + // simple effects for rows within each column + if (ProbF1F2 < alpha) then + begin + if lReport.Count > 0 then + lReport.Add(''); + lReport.Add('COMPARISONS AMONG ROWS WITHIN EACH COLUMN'); + for j := 0 to Nf2cells - 1 do + begin + lReport.Add(''); + lReport.Add('COLUMN %d COMPARISONS', [j+1]); + // move cell sums && counts to cellsums && cellcnts + for i := 0 to Nf1cells - 1 do + begin + for k := 0 to Nf3cells - 1 do + begin + cellsums[i] := wsum[i,j,k]; + cellcnts[i] := ncnt[i,j,k]; + cellvars[i] := wx2[i,j,k]; + end; + end; + value := 1e308; + for i := 0 to Nf1cells - 1 do + if (cellcnts[j] < value) then value := cellcnts[j]; + + if ScheffeChk.Checked then + ScheffeTest(MSErr, cellsums, cellcnts, minf1, maxf1, N, posthocAlpha, lReport); + if TukeyHSDChk.Checked and equal_grp then + Tukey(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, lReport); + if TukeyBChk.Checked and equal_grp then + TukeyBTest(MSErr, DFErr, cellsums, cellcnts, minf1, maxf1, value, posthocAlpha, lReport); + if TukeyKramerChk.Checked and equal_grp then + Tukey_Kramer(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, lReport); + // if (BonferroniChk.Checked) then + // Bonferroni(cellsums,cellcnts,cellvars,minf1,maxf1, lReport); + // if (OrthogonalChk.Checked) then + // CONTRASTS(MSErr,DFErr,cellsums,cellcnts,minf1,maxf1,0.05, lReport); + if NewmanKeulsChk.Checked and equal_grp then + Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, lReport); + end; + end; + + // simple effects for columns within each slice + if (ProbF2F3 < alpha) then + begin + if lReport.Count > 0 then + lReport.Add(''); + lReport.Add('COMPARISONS AMONG COLUMNS WITHIN EACH SLICE'); + for k := 0 to Nf3cells - 1 do + begin + lReport.Add(''); + lReport.Add('SLICE %d COMPARISONS', [k+1]); + // move cell sums && counts to cellsums && cellcnts + for j := 0 to Nf2cells - 1 do + begin + for i := 0 to Nf1cells - 1 do + begin + cellsums[j] := wsum[i,j,k]; + cellcnts[j] := ncnt[i,j,k]; + cellvars[j] := wx2[i,j,k]; + end; + end; + value := 1e308; + for j := 0 to Nf2cells-1 do + if (cellcnts[j] < value) then value := cellcnts[j]; + + if ScheffeChk.Checked then + ScheffeTest(MSErr, cellsums, cellcnts, minf2, maxf2, N, posthocAlpha, lReport); + if TukeyHSDChk.Checked and equal_grp then + Tukey(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, lReport); + if TukeyBChk.Checked and equal_grp then + TukeyBTest(MSErr, DFErr, cellsums, cellcnts, minf2, maxf2, value, posthocAlpha, lReport); + if TukeyKramerChk.Checked and equal_grp then + Tukey_Kramer(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, lReport); + // if (BonferroniChk.Checked) then + // Bonferroni(cellsums, cellcnts, cellvars, minf2, maxf2, posthocAlpha, lReport); + // if (OrthogonalChk.Checked) then + // CONTRASTS(MSErr, DFErr, cellsums, cellcnts, minf2, maxf2, posthocAlpha, lReport); + if NewmanKeulsChk.Checked and equal_grp then + Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, minf2, maxf2, posthocAlpha, lReport); + end; + end; + + // simple effects for rows within each slice + if (ProbF1F3 < alpha) then + begin + if lReport.Count > 0 then + lReport.Add(''); + lReport.Add('COMPARISONS AMONG ROWS WITHIN EACH SLICE'); + for k := 0 to Nf3cells - 1 do + begin + lReport.Add(''); + lReport.Add('SLICE %d COMPARISONS', [k+1]); + // move cell sums && counts to cellsums && cellcnts + for i := 0 to Nf1cells - 1 do + begin + for j := 0 to Nf2cells - 1 do + begin + cellsums[j] := wsum[i,j,k]; + cellcnts[j] := ncnt[i,j,k]; + cellvars[j] := wx2[i,j,k]; + end; + end; + value := 1e308; + for i := 0 to Nf1cells - 1 do + if (cellcnts[i] < value) then value := cellcnts[i]; + + if ScheffeChk.Checked then + ScheffeTest(MSErr, cellsums, cellcnts, minf1, maxf1, N, posthocAlpha, lReport); + if TukeyHSDChk.Checked and equal_grp then + Tukey(MSErr,DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, lReport); + if TukeyBChk.Checked and equal_grp then + TukeyBTest(MSErr, DFErr, cellsums, cellcnts, minf1, maxf1, value, posthocAlpha, lReport); + if TukeyKramerChk.Checked and equal_grp then + Tukey_Kramer(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, lReport); + // if (BonferroniChk.Checked) then + // Bonferroni(cellsums,cellcnts,cellvars,minf1,maxf1, posthocAlpha, lReport); + // if (OrthogonalChk.Checked) then + // CONTRASTS(MSErr,DFErr,cellsums,cellcnts,minf1,maxf1,posthocAlpha, lReport); + if NewmanKeulsChk.Checked and equal_grp then + Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, minf1, maxf1, posthocAlpha, lReport); + end; + end; + + FPosthocReportFrame.DisplayReport(lReport); + PosthocPage.TabVisible := true; + + finally + lReport.Free; + end; +end; + + +procedure TOneCaseAnovaForm.Plot3DChkChange(Sender: TObject); +begin + if FSeries <> nil then + begin + if Plot3DChk.Checked then + FSeries.Depth := 20 + else + FSeries.Depth := 0; + end; +end; + + +procedure TOneCaseAnovaForm.ShowPlotsChkChange(Sender: TObject); +begin + Plot3DChk.Enabled := ShowPlotsChk.Checked; end; @@ -2410,15 +2005,15 @@ begin // Factor 3 can be left empty to distinguish betwee two-way and three-way ANOVA. - if (OverAllAlphaEdit.Text = '') then + if (OverallAlphaEdit.Text = '') then begin - AControl := OverAllAlphaEdit; + AControl := OverallAlphaEdit; AMsg := 'No value specified for overall alpha.'; exit; end; - if not TryStrToFloat(OverAllAlphaEdit.Text, X) then + if not TryStrToFloat(OverallAlphaEdit.Text, X) then begin - AControl := OverAllAlphaEdit; + AControl := OverallAlphaEdit; AMsg := 'Overall alpha is not a valid number.'; exit; end; diff --git a/applications/lazstats/source/forms/analysis/multivariate/medianpolishunit.pas b/applications/lazstats/source/forms/analysis/multivariate/medianpolishunit.pas index cd388153e..d74c0d2fd 100644 --- a/applications/lazstats/source/forms/analysis/multivariate/medianpolishunit.pas +++ b/applications/lazstats/source/forms/analysis/multivariate/medianpolishunit.pas @@ -54,7 +54,7 @@ type procedure FormActivate(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ResetBtnClick(Sender: TObject); - procedure VarListSelectionChange(Sender: TObject; User: boolean); + procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean); private { private declarations } @@ -84,7 +84,7 @@ implementation uses Math, - Utils, MatrixUnit; + MatrixUnit; { TMedianPolishForm }