diff --git a/applications/lazstats/data/ABCNested.laz b/applications/lazstats/data/ABCNested.laz new file mode 100644 index 000000000..ae9802f20 --- /dev/null +++ b/applications/lazstats/data/ABCNested.laz @@ -0,0 +1,305 @@ +54 +4 +A +VARIABLE 1 +1 +I +0 +99999 +L +B +VARIABLE 2 +1 +I +0 +99999 +L +C +VARIABLE 3 +1 +I +0 +99999 +L +Dep +VARIABLE 4 +4 +F +1 +99999 +L +Case 0 +A +B +C +Dep +Case 1 +1 +1 +1 +1.00 +Case 2 +1 +1 +1 +3.00 +Case 3 +1 +1 +1 +4.00 +Case 4 +1 +2 +1 +2.00 +Case 5 +1 +2 +1 +3.00 +Case 6 +1 +2 +1 +5.00 +Case 7 +1 +3 +1 +3.00 +Case 8 +1 +3 +1 +3.00 +Case 9 +1 +3 +1 +6.00 +Case 10 +2 +4 +1 +2.00 +Case 11 +2 +4 +1 +4.00 +Case 12 +2 +4 +1 +5.00 +Case 13 +2 +5 +1 +3.00 +Case 14 +2 +5 +1 +4.00 +Case 15 +2 +5 +1 +5.00 +Case 16 +2 +6 +1 +4.00 +Case 17 +2 +6 +1 +5.00 +Case 18 +2 +6 +1 +6.00 +Case 19 +3 +7 +1 +3.00 +Case 20 +3 +7 +1 +3.00 +Case 21 +3 +7 +1 +5.00 +Case 22 +3 +8 +1 +4.00 +Case 23 +3 +8 +1 +5.00 +Case 24 +3 +8 +1 +6.00 +Case 25 +3 +9 +1 +6.00 +Case 26 +3 +9 +1 +6.00 +Case 27 +3 +9 +1 +8.00 +Case 28 +1 +1 +2 +2.00 +Case 29 +1 +1 +2 +4.00 +Case 30 +1 +1 +2 +4.00 +Case 31 +1 +2 +2 +2.00 +Case 32 +1 +2 +2 +3.00 +Case 33 +1 +2 +2 +6.00 +Case 34 +1 +3 +2 +4.00 +Case 35 +1 +3 +2 +4.00 +Case 36 +1 +3 +2 +7.00 +Case 37 +2 +4 +2 +3.00 +Case 38 +2 +4 +2 +5.00 +Case 39 +2 +4 +2 +6.00 +Case 40 +2 +5 +2 +4.00 +Case 41 +2 +5 +2 +5.00 +Case 42 +2 +5 +2 +5.00 +Case 43 +2 +6 +2 +2.00 +Case 44 +2 +6 +2 +3.00 +Case 45 +2 +6 +2 +4.00 +Case 46 +3 +7 +2 +2.00 +Case 47 +3 +7 +2 +2.00 +Case 48 +3 +7 +2 +4.00 +Case 49 +3 +8 +2 +5.00 +Case 50 +3 +8 +2 +6.00 +Case 51 +3 +8 +2 +7.00 +Case 52 +3 +9 +2 +6.00 +Case 53 +3 +9 +2 +6.00 +Case 54 +3 +9 +2 +7.00 diff --git a/applications/lazstats/source/forms/analysis/comparisons/abcnestedunit.lfm b/applications/lazstats/source/forms/analysis/comparisons/abcnestedunit.lfm index 65d576dfd..5a828a0cd 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/abcnestedunit.lfm +++ b/applications/lazstats/source/forms/analysis/comparisons/abcnestedunit.lfm @@ -3,7 +3,7 @@ inherited ABCNestedForm: TABCNestedForm Height = 481 Top = 191 Width = 843 - Caption = 'ABCNestedForm' + Caption = 'Three-Factor Nested ANOVA' ClientHeight = 481 ClientWidth = 843 inherited ParamsPanel: TPanel @@ -14,23 +14,23 @@ inherited ABCNestedForm: TABCNestedForm inherited CloseBtn: TButton Left = 274 Top = 440 - TabOrder = 17 + TabOrder = 16 end inherited ComputeBtn: TButton Left = 190 Top = 440 - TabOrder = 16 + TabOrder = 15 end inherited ResetBtn: TButton Left = 128 Top = 440 - TabOrder = 15 + TabOrder = 14 end inherited HelpBtn: TButton Tag = 170 Left = 69 Top = 440 - TabOrder = 14 + TabOrder = 13 end inherited ButtonBevel: TBevel Top = 424 @@ -40,9 +40,9 @@ inherited ABCNestedForm: TABCNestedForm AnchorSideTop.Control = Label1 AnchorSideTop.Side = asrBottom AnchorSideRight.Control = AInBtn - AnchorSideBottom.Control = OptionsGroup + AnchorSideBottom.Control = PlotOptionsGroup Left = 0 - Height = 285 + Height = 327 Top = 17 Width = 144 Anchors = [akTop, akLeft, akRight, akBottom] @@ -209,12 +209,12 @@ inherited ABCNestedForm: TABCNestedForm AnchorSideLeft.Control = AInBtn AnchorSideLeft.Side = asrBottom AnchorSideBottom.Control = FactorBEdit - Left = 186 + Left = 184 Height = 15 Top = 177 Width = 115 Anchors = [akLeft, akBottom] - BorderSpacing.Left = 8 + BorderSpacing.Left = 6 BorderSpacing.Bottom = 2 Caption = 'Factor B (Nested in A)' ParentColor = False @@ -223,12 +223,12 @@ inherited ABCNestedForm: TABCNestedForm AnchorSideLeft.Control = AInBtn AnchorSideLeft.Side = asrBottom AnchorSideBottom.Control = DepEdit - Left = 186 + Left = 184 Height = 15 Top = 25 Width = 102 Anchors = [akLeft, akBottom] - BorderSpacing.Left = 8 + BorderSpacing.Left = 6 BorderSpacing.Bottom = 2 Caption = 'Dependent Variable' ParentColor = False @@ -240,12 +240,12 @@ inherited ABCNestedForm: TABCNestedForm AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = AOutBtn AnchorSideBottom.Side = asrBottom - Left = 186 + Left = 184 Height = 23 Top = 118 - Width = 143 + Width = 145 Anchors = [akLeft, akRight, akBottom] - BorderSpacing.Left = 8 + BorderSpacing.Left = 6 BorderSpacing.Bottom = 12 ReadOnly = True TabOrder = 6 @@ -258,12 +258,12 @@ inherited ABCNestedForm: TABCNestedForm AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = BOutBtn AnchorSideBottom.Side = asrBottom - Left = 186 + Left = 184 Height = 23 Top = 194 - Width = 143 + Width = 145 Anchors = [akLeft, akRight, akBottom] - BorderSpacing.Left = 8 + BorderSpacing.Left = 6 BorderSpacing.Bottom = 12 ReadOnly = True TabOrder = 9 @@ -276,12 +276,12 @@ inherited ABCNestedForm: TABCNestedForm AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = DepOutBtn AnchorSideBottom.Side = asrBottom - Left = 186 + Left = 184 Height = 23 Top = 42 - Width = 143 + Width = 145 Anchors = [akLeft, akRight, akBottom] - BorderSpacing.Left = 8 + BorderSpacing.Left = 6 BorderSpacing.Bottom = 12 ReadOnly = True TabOrder = 3 @@ -294,12 +294,12 @@ inherited ABCNestedForm: TABCNestedForm AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = COutBtn AnchorSideBottom.Side = asrBottom - Left = 186 + Left = 184 Height = 23 Top = 270 - Width = 143 + Width = 145 Anchors = [akLeft, akRight, akBottom] - BorderSpacing.Left = 8 + BorderSpacing.Left = 6 BorderSpacing.Bottom = 12 ReadOnly = True TabOrder = 12 @@ -309,49 +309,59 @@ inherited ABCNestedForm: TABCNestedForm AnchorSideLeft.Control = AInBtn AnchorSideLeft.Side = asrBottom AnchorSideBottom.Control = FactorCEdit - Left = 186 + Left = 184 Height = 15 Top = 253 Width = 88 Anchors = [akLeft, akBottom] - BorderSpacing.Left = 8 + BorderSpacing.Left = 6 BorderSpacing.Bottom = 2 Caption = 'Factor C Variable' ParentColor = False end - object OptionsGroup: TRadioGroup[23] + object PlotOptionsGroup: TGroupBox[23] AnchorSideLeft.Control = ParamsPanel - AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = ButtonBevel - Left = 8 - Height = 114 - Top = 310 - Width = 239 + Left = 0 + Height = 72 + Top = 352 + Width = 106 Anchors = [akLeft, akBottom] - AutoFill = True AutoSize = True - BorderSpacing.Left = 8 - BorderSpacing.Right = 8 Caption = 'Plot options' - ChildSizing.LeftRightSpacing = 12 - ChildSizing.TopBottomSpacing = 6 - ChildSizing.HorizontalSpacing = 16 - ChildSizing.VerticalSpacing = 2 - ChildSizing.EnlargeHorizontal = crsHomogenousChildResize - ChildSizing.EnlargeVertical = crsHomogenousChildResize - ChildSizing.ShrinkHorizontal = crsScaleChilds - ChildSizing.ShrinkVertical = crsScaleChilds - ChildSizing.Layout = cclLeftToRightThenTopToBottom - ChildSizing.ControlsPerLine = 1 - ClientHeight = 94 - ClientWidth = 235 - Items.Strings = ( - 'Plot means using 2D Horizontal Bars' - 'Plot means using 3D Horizontal Bars' - 'Plot means using 2D Vertical Bars' - 'Plot means using 3D Vertical Bars' - ) - TabOrder = 13 + ClientHeight = 52 + ClientWidth = 102 + TabOrder = 17 + object ShowPlotsChk: TCheckBox + AnchorSideLeft.Control = PlotOptionsGroup + AnchorSideTop.Control = PlotOptionsGroup + Left = 12 + Height = 19 + Top = 6 + Width = 78 + BorderSpacing.Left = 12 + BorderSpacing.Top = 6 + BorderSpacing.Right = 12 + Caption = 'Show plots' + Checked = True + OnChange = ShowPlotsChkChange + State = cbChecked + TabOrder = 0 + end + object Plot3DChk: TCheckBox + AnchorSideLeft.Control = ShowPlotsChk + AnchorSideTop.Control = ShowPlotsChk + AnchorSideTop.Side = asrBottom + Left = 32 + Height = 19 + Top = 25 + Width = 34 + BorderSpacing.Left = 20 + BorderSpacing.Bottom = 8 + Caption = '3D' + OnChange = Plot3DChkChange + TabOrder = 1 + end end end inherited ParamsSplitter: TSplitter @@ -364,5 +374,19 @@ inherited ABCNestedForm: TABCNestedForm Width = 485 ActivePage = ReportPage TabIndex = 0 + inherited ReportPage: TTabSheet + Caption = 'ANOVA Results' + end + object MeansPage: TTabSheet[1] + Caption = 'Means' + end + inherited ChartPage: TTabSheet[2] + Caption = 'Plots' + end + end + object ChartStyles: TChartStyles[3] + Styles = <> + Left = 520 + Top = 175 end end diff --git a/applications/lazstats/source/forms/analysis/comparisons/abcnestedunit.pas b/applications/lazstats/source/forms/analysis/comparisons/abcnestedunit.pas index 86cc34888..4b5127e72 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/abcnestedunit.pas +++ b/applications/lazstats/source/forms/analysis/comparisons/abcnestedunit.pas @@ -1,19 +1,36 @@ +{ Test file: ABCNested.laz (imported from OpenStat sample data zip file) + Dependent: Dep + Factor A : A + Factor B : B + Factor C : C +} + unit ABCNestedUnit; + {$mode objfpc}{$H+} +{.$DEFINE SHOW_OLD_PLOTS} + interface uses - Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, - StdCtrls, Buttons, ExtCtrls, - MainUnit, GraphLib, Globals, BasicStatsReportAndChartFormUnit; + Classes, SysUtils, FileUtil, TAStyles, Forms, Controls, Graphics, Dialogs, + StdCtrls, Buttons, ExtCtrls, ComCtrls, LCLVersion, + TACustomSeries, + {$IFDEF SHOW_OLD_PLOTS} + GraphLib, + {$ENDIF} + MainUnit, Globals, ReportFrameUnit, BasicStatsReportAndChartFormUnit; type { TABCNestedForm } TABCNestedForm = class(TBasicStatsReportAndChartForm) + ChartStyles: TChartStyles; + ShowPlotsChk: TCheckBox; + Plot3DChk: TCheckBox; FactorCEdit: TEdit; FactorAEdit: TEdit; AInBtn: TBitBtn; @@ -26,14 +43,15 @@ type CInBtn: TBitBtn; DepOutBtn: TBitBtn; COutBtn: TBitBtn; + PlotOptionsGroup: TGroupBox; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; Memo1: TLabel; - OptionsGroup: TRadioGroup; Panel1: TPanel; + MeansPage: TTabSheet; VarList: TListBox; procedure AInBtnClick(Sender: TObject); procedure AOutBtnClick(Sender: TObject); @@ -43,33 +61,46 @@ type procedure COutBtnClick(Sender: TObject); procedure DepInBtnClick(Sender: TObject); procedure DepOutBtnClick(Sender: TObject); + procedure Plot3DChkChange(Sender: TObject); + procedure ShowPlotsChkChange(Sender: TObject); procedure VarListDblClick(Sender: TObject); procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean); private CellCount: IntDyneCube; - ASS, BSS, CSS, ASumSqr, BSumSqr, CSumSqr, AMeans, BMeans, ASDs : DblDyneVec; - CMeans, BSDs, CSDs : DblDyneVec; - ACSS,ACSumSqr, ACMeans, ACSDs, ABSS, ABSumSqr, ABMeans, ABSDs : DblDyneMat; + ASS, BSS, CSS, ASumSqr, BSumSqr, CSumSqr, ASDs, BSDs, CSDs : DblDyneVec; + ACSS,ACSumSqr, ACSDs, ABSS, ABSumSqr, ABSDs : DblDyneMat; ACount, BCount, CCount : IntDyneVec; ACCount, ABCount : IntDyneMat; CellSDs, SS, SumSqr, CellMeans : DblDyneCube; MinA, MinB, MaxA, MaxB, NoALevels, NoBLevels, ACol, BCol, YCol : integer; CCol, MinC, MaxC, NoCLevels : integer; - DepVar, FactorA, FactorB, FactorC : string; SSTot, SumSqrTot, TotMean, MSTot, SSA, MSA, SSB, MSB, SSW, MSW : double; SSC, MSC, SSAC, MSAC, SSBwAC, SSAB, MSBwAC : double; TotN, dfA, dfBwA, dfwcell, dftotal, dfC, dfAC, dfBwAC : integer; ColNoSelected: IntDyneVec; - function GetVars: Boolean; + AMeans, BMeans, CMeans: DblDyneVec; + ABMeans, ACMeans: DblDyneMat; + + function GetVariables: Boolean; procedure GetMemory; procedure GetSums; - procedure ShowMeans(AReport: TStrings); + procedure ShowMeans; procedure GetResults; - procedure ShowResults(AReport: TStrings); + procedure ShowResults; procedure ReleaseMemory; procedure TwoWayPlot; + {$IFDEF SHOW_OLD_PLOTS} + procedure OldTwoWayPlot; + {$ENDIF} + + private + FMeansReportFrame: TReportFrame; + FChartCombobox: TCombobox; + FSeries: TChartSeries; + procedure PopulateChartCombobox; + procedure SelectPlot(Sender: TObject); protected procedure AdjustConstraints; override; @@ -90,7 +121,8 @@ implementation {$R *.lfm} uses - Math, MathUnit; + TAChartUtils, TACustomSource, TALegend, TASeries, + Utils, Math, MathUnit, ChartFrameUnit; { TABCNestedForm } @@ -98,8 +130,23 @@ uses constructor TABCNestedForm.Create(AOwner: TComponent); begin inherited; + + FMeansReportFrame := TReportFrame.Create(MeansPage); + FMeansReportFrame.Parent := MeansPage; + FMeansReportFrame.Align := alClient; + InitToolbar(FMeansReportFrame.ReportToolbar, tpTop); + MeansPage.PageIndex := 1; + + FChartFrame.Chart.Margins.Bottom := 0; + AddComboboxToToolbar(FChartFrame.ChartToolbar, 'Plots:', FChartCombobox); + FChartCombobox.OnSelect := @SelectPlot; + + {$IFDEF SHOW_OLD_PLOTS} if GraphFrm = nil then Application.CreateForm(TGraphFrm, GraphFrm); + {$ENDIF} + + PageControl.ActivePageIndex := 0; end; @@ -112,7 +159,6 @@ begin MaxValue([Label2.Width, Label3.Width, Label4.Width, Label5.Width])*2 + AInBtn.Width + VarList.BorderSpacing.Right*2 ); ParamsPanel.Constraints.MinHeight := COutBtn.Top + COutBtn.Height + - VarList.BorderSpacing.Bottom + OptionsGroup.Height + ButtonBevel.Height + CloseBtn.Height + CloseBtn.BorderSpacing.Top; end; @@ -190,23 +236,19 @@ end; procedure TABCNestedForm.Compute; -var - lReport: TStrings; begin - lReport := TStringList.Create; - try - if GetVars then - begin - GetMemory; - GetSums; - ShowMeans(lReport); - GetResults; - ShowResults(lReport); - TwoWayPlot; - ReleaseMemory; - end; - finally - lReport.Free; + if GetVariables then + begin + GetMemory; + GetSums; + ShowMeans; + GetResults; + ShowResults; + TwoWayPlot; + {$IFDEF SHOW_OLD_PLOTS} + OldTwoWayPlot; + {$ENDIF} + ReleaseMemory; end; end; @@ -236,22 +278,59 @@ begin end; -function TABCNestedForm.GetVars: Boolean; +procedure TABCNestedForm.Plot3DChkChange(Sender: TObject); +begin + if FSeries is TBarSeries then + begin + if Plot3dChk.Checked then + TBarSeries(FSeries).Depth := 20 + else + TBarSeries(FSeries).Depth := 0; + end; +end; + + +procedure TABCNestedForm.ShowPlotsChkChange(Sender: TObject); +begin + ChartPage.TabVisible := ShowPlotsChk.Checked; + Plot3DChk.Enabled := ShowPlotsChk.Checked; +end; + + +procedure TABCNestedForm.PopulateChartCombobox; +var + a, b, c: String; + idx: Integer; +begin + idx := FChartCombobox.ItemIndex; + + a := FactorAEdit.Text; + b := FactorBEdit.Text; + c := FactorCEdit.Text; + + FChartCombobox.Items.Clear; + FChartCombobox.Items.Add(a); + FChartCombobox.Items.Add(b); + FChartCombobox.Items.Add(c); + FChartCombobox.Items.Add(Format('%s x %s', [a, b])); + FChartCombobox.Items.Add(Format('%s x %s', [a, c])); + + FChartCombobox.ItemIndex := EnsureRange(idx, 0, FChartCombobox.Items.Count-1); +end; + + +function TABCNestedForm.GetVariables: Boolean; var i, group: integer; strvalue, cellstring: string; begin Result := false; - SetLength(ColNoSelected,4); - DepVar := DepEdit.Text; - FactorA := FactorAEdit.Text; - FactorB := FactorBEdit.Text; - FactorC := FactorCEdit.Text; - ACol := 0; - BCol := 0; - CCol := 0; - YCol := 0; + SetLength(ColNoSelected, 4); + ACol := -1; + BCol := -1; + CCol := -1; + YCol := -1; MinA := MaxInt; MaxA := -MaxInt; MinB := MaxInt; @@ -261,28 +340,28 @@ begin for i := 1 to NoVariables do begin strvalue := Trim(OS3MainFrm.DataGrid.Cells[i,0]); - if FactorA = strvalue then + if FactorAEdit.Text = strvalue then begin ACol := i; ColNoSelected[0] := i; end; - if FactorB = strvalue then + if FactorBEdit.Text = strvalue then begin BCol := i; ColNoSelected[1] := i; end; - if FactorC = strvalue then + if FactorCEdit.Text = strvalue then begin CCol := i; ColNoSelected[2] := i; end; - if DepVar = strvalue then + if DepEdit.Text = strvalue then begin YCol := i; ColNoSelected[3] := i; end; end; - if (ACol = 0) or (BCol = 0) or (CCol = 0) or (YCol = 0) then + if (ACol = -1) or (BCol = -1) or (CCol = -1) or (YCol = -1) then begin MessageDlg('Select a variable for each entry box.', mtError, [mbOK], 0); exit; @@ -528,62 +607,74 @@ begin end; -procedure TABCNestedForm.ShowMeans(AReport: TStrings); +procedure TABCNestedForm.ShowMeans; var + lReport: TStrings; i, j, k : integer; begin - AReport.Add('Nested ANOVA by Bill Miller'); - AReport.Add('File Analyzed: %s', [OS3MainFrm.FileNameEdit.Text]); - AReport.Add(''); + lReport := TStringList.Create; + try + lReport.Add('Nested ANOVA by Bill Miller'); + lReport.Add(''); + lReport.Add('File analyzed: %s', [OS3MainFrm.FileNameEdit.Text]); + lReport.Add('Factor A: %s', [FactorAEdit.Text]); + lReport.Add('Factor B: %s', [FactorBEdit.Text]); + lReport.Add('Factor C: %s', [FactorCEdit.Text]); + lReport.Add(''); - AReport.Add('CELL MEANS'); - AReport.Add('A LEVEL BLEVEL CLEVEL MEAN STD.DEV.'); - for i := 0 to NoALevels-1 do - for j := 0 to NoBLevels-1 do - for k := 0 to NoCLevels-1 do - if CellCount[j,i,k] > 0 then - AReport.Add('%5d %5d %5d %10.4f %10.4f', [i+MinA, j+MinB, k+MinC, CellMeans[j,i,k], CellSDs[j,i,k]]); - AReport.Add(''); + lReport.Add('CELL MEANS'); + lReport.Add('A LEVEL BLEVEL CLEVEL MEAN STD.DEV.'); + for i := 0 to NoALevels-1 do + for j := 0 to NoBLevels-1 do + for k := 0 to NoCLevels-1 do + if CellCount[j,i,k] > 0 then + lReport.Add('%5d %5d %5d %10.4f %10.4f', [i+MinA, j+MinB, k+MinC, CellMeans[j,i,k], CellSDs[j,i,k]]); + lReport.Add(''); - AReport.Add('A MARGIN MEANS'); - AReport.Add('A LEVEL MEAN STD.DEV.'); - for i := 0 to NoALevels-1 do - AReport.Add('%5d %10.3f %10.3f', [i+MinA, AMeans[i], ASDs[i]]); - AReport.Add(''); + lReport.Add('A MARGIN MEANS'); + lReport.Add('A LEVEL MEAN STD.DEV.'); + for i := 0 to NoALevels-1 do + lReport.Add('%5d %10.3f %10.3f', [i+MinA, AMeans[i], ASDs[i]]); + lReport.Add(''); - AReport.Add('B MARGIN MEANS'); - AReport.Add('B LEVEL MEAN STD.DEV.'); - for i := 0 to NoBLevels-1 do - if BCount[i] > 0 then - AReport.Add('%5d %10.3f %10.3f', [i+MinB, BMeans[i], BSDs[i]]); - AReport.Add(''); + lReport.Add('B MARGIN MEANS'); + lReport.Add('B LEVEL MEAN STD.DEV.'); + for i := 0 to NoBLevels-1 do + if BCount[i] > 0 then + lReport.Add('%5d %10.3f %10.3f', [i+MinB, BMeans[i], BSDs[i]]); + lReport.Add(''); - AReport.Add('C MARGIN MEANS'); - AReport.Add('C LEVEL MEAN STD.DEV.'); - for i := 0 to NoCLevels-1 do - if CCount[i] > 0 then - AReport.Add('%5d %10.3f %10.3f', [i+MinC, CMeans[i], CSDs[i]]); + lReport.Add('C MARGIN MEANS'); + lReport.Add('C LEVEL MEAN STD.DEV.'); + for i := 0 to NoCLevels-1 do + if CCount[i] > 0 then + lReport.Add('%5d %10.3f %10.3f', [i+MinC, CMeans[i], CSDs[i]]); - AReport.Add(''); - AReport.Add('AB MARGIN MEANS'); - AReport.Add('A LEVEL B LEVEL MEAN STD.DEV.'); - for i := 0 to NoALevels-1 do - for j := 0 to NoBLevels-1 do - if ABCount[i,j] > 0 then - AReport.Add('%5d %5D %10.3f %10.3f', [i+MinA, j+MinB, ABMeans[i,j], ABSDs[i,j]]); - AReport.Add(''); + lReport.Add(''); + lReport.Add('AB MARGIN MEANS'); + lReport.Add('A LEVEL B LEVEL MEAN STD.DEV.'); + for i := 0 to NoALevels-1 do + for j := 0 to NoBLevels-1 do + if ABCount[i,j] > 0 then + lReport.Add('%5d %5D %10.3f %10.3f', [i+MinA, j+MinB, ABMeans[i,j], ABSDs[i,j]]); + lReport.Add(''); - AReport.Add('AC MARGIN MEANS'); - AReport.Add('A LEVEL C LEVEL MEAN STD.DEV.'); - for i := 0 to NoALevels-1 do - for j := 0 to NoCLevels-1 do - if ACCount[i,j] > 0 then - AReport.Add('%5d %5D %10.3f %10.3f',[i+MinA, j+MinC, ACMeans[i,j], ACSDs[i,j]]); - AReport.Add(''); + lReport.Add('AC MARGIN MEANS'); + lReport.Add('A LEVEL C LEVEL MEAN STD.DEV.'); + for i := 0 to NoALevels-1 do + for j := 0 to NoCLevels-1 do + if ACCount[i,j] > 0 then + lReport.Add('%5d %5D %10.3f %10.3f',[i+MinA, j+MinC, ACMeans[i,j], ACSDs[i,j]]); + lReport.Add(''); - AReport.Add('GRAND MEAN = %10.3f', [TotMean]); - AReport.Add(''); -// OutputFrm.ShowModal; + lReport.Add('GRAND MEAN = %10.3f', [TotMean]); + lReport.Add(''); + + FMeansReportFrame.DisplayReport(lReport); + + finally + lReport.Free; + end; end; @@ -685,38 +776,54 @@ begin end; -procedure TABCNestedForm.ShowResults(AReport: TStrings); -VAR +procedure TABCNestedForm.ShowResults; +var + lReport: TStrings; F, PF : double; begin - AReport.Add(''); - AReport.Add('ANOVA TABLE'); - AReport.Add('SOURCE D.F. SS MS F PROB.'); + lReport := TStringList.Create; + try + lReport.Add('Nested ANOVA by Bill Miller'); + lReport.Add(''); + lReport.Add('File analyzed: %s', [OS3MainFrm.FileNameEdit.Text]); + lReport.Add('Factor A: %s', [FactorAEdit.Text]); + lReport.Add('Factor B: %s', [FactorBEdit.Text]); + lReport.Add('Factor C: %s', [FactorCEdit.Text]); + lReport.Add(''); + lReport.Add('ANOVA TABLE'); + lReport.Add('------------------------------------------------------------'); + lReport.Add('SOURCE D.F. SS MS F PROB. '); + lReport.Add('--------- ---- ---------- ---------- --------- ---------'); - F := MSA / MSW; - PF := ProbF(F,dfA,dfwcell); - AReport.Add('A %4D %10.3f%10.3f%10.3f%10.3f', [dfA, SSA, MSA, F, PF]); + F := MSA / MSW; + PF := ProbF(F,dfA,dfwcell); + lReport.Add('A %4d %10.3f %10.3f %9.3f %9.3f', [dfA, SSA, MSA, F, PF]); - F := MSB / MSW; - PF := ProbF(F,dfBwA,dfwcell); - AReport.Add('B(A) %4D %10.3f%10.3f%10.3f%10.3f', [dfBwA, SSB, MSB, F, PF]); + F := MSB / MSW; + PF := ProbF(F,dfBwA,dfwcell); + lReport.Add('B(A) %4d %10.3f %10.3f %9.3f %9.3f', [dfBwA, SSB, MSB, F, PF]); - F := MSC / MSW; - PF := ProbF(F,dfC,dfwcell); - AReport.Add('C %4D %10.3f%10.3f%10.3f%10.3f', [dfC, SSC, MSC, F, PF]); + F := MSC / MSW; + PF := ProbF(F,dfC,dfwcell); + lReport.Add('C %4d %10.3f %10.3f %9.3f %9.3f', [dfC, SSC, MSC, F, PF]); - F := MSAC / MSW; - PF := ProbF(F,dfAC,dfwcell); - AReport.Add('AxC %4D %10.3f%10.3f%10.3f%10.3f', [dfAC, SSAC, MSAC, F, PF]); + F := MSAC / MSW; + PF := ProbF(F,dfAC,dfwcell); + lReport.Add('AxC %4d %10.3f %10.3f %9.3f %9.3f', [dfAC, SSAC, MSAC, F, PF]); - F := MSBwAC / MSW; - PF := ProbF(F,dfBwAC,dfwcell); - AReport.Add('B(A)xC %4D %10.3f%10.3f%10.3f%10.3f', [dfBwAC, SSBwAC, MSBwAC, F, PF]); + F := MSBwAC / MSW; + PF := ProbF(F,dfBwAC,dfwcell); + lReport.Add('B(A)xC %4d %10.3f %10.3f %9.3f %9.3f', [dfBwAC, SSBwAC, MSBwAC, F, PF]); - AReport.Add('w.cells %4D %10.3f%10.3f', [dfwcell, SSW, MSW]); - AReport.Add('Total %4D %10.3f', [dftotal, SSTot]); + lReport.Add('w.cells %4d %10.3f %10.3f', [dfwcell, SSW, MSW]); + lReport.Add('Total %4d %10.3f', [dftotal, SSTot]); + lReport.Add('------------------------------------------------------------'); - FReportFrame.DisplayReport(AReport); + FReportFrame.DisplayReport(lReport); + + finally + lReport.Free; + end; end; @@ -725,11 +832,11 @@ begin ColNoSelected := nil; ABSDs := nil; ABCount := nil; - ABMeans := nil; +// ABMeans := nil; ABSumSqr := nil; ABSS := nil; ACSDs := nil; - ACMeans := nil; +// ACMeans := nil; ACCount := nil; ACSumSqr := nil; ACSS := nil; @@ -739,9 +846,9 @@ begin CCount := nil; BCount := nil; ACount := nil; - CMeans := nil; - BMeans := nil; - AMeans := nil; +// CMeans := nil; +// BMeans := nil; +// AMeans := nil; CSumSqr := nil; BSumSqr := nil; ASumSqr := nil; @@ -762,6 +869,11 @@ var begin inherited; + if FMeansReportFrame <> nil then + FMeansReportFrame.Clear; + if FChartCombobox <> nil then + FChartCombobox.Items.Clear; + VarList.Items.Clear; for i := 1 to NoVariables do VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); @@ -771,14 +883,156 @@ begin FactorCEdit.Clear; DepEdit.Clear; - OptionsGroup.ItemIndex := 3; - OptionsGroup.ItemIndex := 3; - UpdateBtnStates; end; +procedure TABCNestedForm.SelectPlot(Sender: TObject); +var + i, j, k, idx: Integer; + item: PChartDataItem; +begin + ChartStyles.Styles.Clear; + FSeries.Clear; + + case FChartComboBox.ItemIndex of + 0: begin // Plot means vs factor A + FSeries.ListSource.YCount := 1; + for i := 0 to NoALevels-1 do + FSeries.AddXY(MinA + i, AMeans[i], IntToStr(MinA + i)); + FChartFrame.SetXTitle(FactorAEdit.Text + ' codes'); + FChartFrame.SetTitle('Factor ' + FactorAEdit.Text); + end; + 1: begin // Plot means vs factor B + FSeries.ListSource.YCount := 1; + for i := 0 to NoBLevels-1 do + FSeries.AddXY(MinB + i, BMeans[i], IntToStr(MinB + i)); + FChartFrame.SetXTitle(FactorBEdit.Text + ' codes'); + FChartFrame.SetTitle('Factor ' + FactorBEdit.Text); + end; + 2: begin // Plot means vs factor C + FSeries.ListSource.YCount := 1; + for i := 0 to NoCLevels-1 do + FSeries.AddXY(MinC + i, CMeans[i], IntToStr(MinC + i)); + FChartFrame.SetXTitle(FactorCEdit.Text + ' codes'); + FChartFrame.SetTitle('Factor ' + FactorCEdit.Text); + end; + 3: begin // Plot interaction AxB + FSeries.ListSource.YCount := NoALevels; + for j := 0 to NoBLevels-1 do + begin + idx := FSeries.AddXY(MinB + j, NaN, IntToStr(MinB + j)); + item := FSeries.Source.Item[idx]; + for i := 0 to NoALevels-1 do + item^.SetY(i, ABMeans[i, j]); + end; + FChartFrame.SetTitle(Format('Factor "%s" x Factor "%s"', [ + FactorAEdit.Text, FactorBEdit.Text])); + FChartFrame.SetXTitle(FactorBEdit.Text + ' codes'); + for i := 0 to NoALevels-1 do + with TChartStyle(ChartStyles.Styles.Add) do + begin + Brush.Color := DATA_COLORS[i mod Length(DATA_COLORS)]; + UseBrush := true; + Text := Format('%s = %s', [FactorAEdit.Text, IntToStr(MinA+i)]); + end; + end; + 4: begin // Plot interaction AxC + FSeries.ListSource.YCount := NoALevels; + for k := 0 to NoCLevels-1 do + begin + idx := FSeries.AddXY(MinC + k, NaN, IntToStr(MinC + k)); + item := FSeries.Source.Item[idx]; + for i := 0 to NoALevels-1 do + item^.SetY(i, ACMeans[i, k]); + end; + FChartFrame.SetTitle(Format('Factor "%s" x Factor "%s"', [ + FactorAEdit.Text, FactorCEdit.Text])); + FChartFrame.SetXTitle(FactorCEdit.Text + ' codes'); + for i := 0 to NoALevels-1 do + with TChartStyle(ChartStyles.Styles.Add) do + begin + Brush.Color := DATA_COLORS[i mod Length(DATA_COLORS)]; + UseBrush := true; + Text := Format('%s = %s', [FactorAEdit.Text, IntToStr(MinA+i)]); + end; + end; + end; + (* + GetDataIndices(ix, iy,iz); + if (ix = 1) and (iy = 2) then + begin + FSeries.ListSource.YCount := NF2Cells; + for i := 0 to NF1Cells-1 do + begin + idx := FSeries.AddXY(minF1 + i, NaN, IntToStr(minF1 + i)); + item := FSeries.Source.Item[idx]; + for j := 0 to NF2Cells-1 do + item^.SetY(j, wsum[i,j,iz] / ncnt[i,j,iz]); + end; + FChartFrame.SetTitle(Format('Factor "%s" x Factor "%s"' + LineEnding + '"%s" = %d', [ + Factor1Edit.Text, Factor2Edit.Text, Factor3Edit.Text, MinF3 + iz])); + FChartFrame.SetXTitle(Factor1Edit.Text + ' codes'); + for j := 0 to NF2Cells-1 do + with TChartStyle(FStyles.styles.Add) do + begin + Brush.Color := DATA_COLORS[j mod Length(DATA_COLORS)]; + UseBrush := True; + Text := Format('%s = %s', [Factor2Edit.Text, IntToStr(MinF2 + j)]); + end; + end + else *) + + if (FSeries is TBarSeries) then + begin + if ChartStyles.Styles.Count > 0 then + begin + TBarSeries(FSeries).Styles := ChartStyles; + FSeries.Legend.Multiplicity := lmStyle; + end else + FSeries.Legend.Multiplicity := lmSingle; + end; + + FChartFrame.Chart.BottomAxis.Marks.Source := FSeries.Source; + FChartFrame.Chart.BottomAxis.Marks.Style := smsLabel; + FChartFrame.Chart.Legend.Visible := FSeries.Source.YCount > 1; + + FChartFrame.UpdateBtnStates; + +end; + + procedure TABCNestedForm.TwoWayPlot; +begin + if not ShowPlotsChk.Checked then + begin + ChartPage.TabVisible := false; + exit; + end; + FChartFrame.Clear; // this destroys the series + FChartFrame.SetYTitle('Mean'); + + 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; + + FChartCombobox.Parent.Left := 0; + PopulateChartCombobox; + SelectPlot(nil); + + ChartPage.TabVisible := true; +end; + + +{$IFDEF SHOW_OLD_PLOTS} +procedure TABCNestedForm.OldTwoWayPlot; var plottype, i, j, k : integer; maxmean, XBar : double; @@ -808,8 +1062,8 @@ begin end; GraphFrm.nosets := 1; GraphFrm.nbars := NoALevels; - GraphFrm.Heading := FactorA; - title := FactorA + ' Group Codes'; + GraphFrm.Heading := FactorAEdit.Text; + title := FactorAEdit.Text + ' Group Codes'; GraphFrm.XTitle := title; GraphFrm.YTitle := 'Mean'; GraphFrm.barwideprop := 0.5; @@ -843,7 +1097,7 @@ begin GraphFrm.nosets := 1; GraphFrm.nbars := NoBLevels; GraphFrm.Heading := 'FACTOR B'; - title := FactorB + ' Group Codes'; + title := FactorBEdit.Text + ' Group Codes'; GraphFrm.XTitle := title; GraphFrm.YTitle := 'Mean'; GraphFrm.barwideprop := 0.5; @@ -877,7 +1131,7 @@ begin GraphFrm.nosets := 1; GraphFrm.nbars := NoCLevels; GraphFrm.Heading := 'FACTOR C'; - title := FactorB + ' Group Codes'; + title := FactorBEdit.Text + ' Group Codes'; GraphFrm.XTitle := title; GraphFrm.YTitle := 'Mean'; GraphFrm.barwideprop := 0.5; @@ -922,7 +1176,7 @@ begin GraphFrm.nosets := NoALevels; GraphFrm.nbars := NoBLevels; GraphFrm.Heading := 'FACTOR A x Factor B within C' + IntToStr(k+1); - title := FactorB + ' Group Codes'; + title := FactorBEdit.Text + ' Group Codes'; GraphFrm.XTitle := title; GraphFrm.YTitle := 'Mean'; GraphFrm.barwideprop := 0.5; @@ -966,7 +1220,7 @@ begin GraphFrm.nosets := NoALevels; GraphFrm.nbars := NoCLevels; GraphFrm.Heading := 'FACTOR A x Factor C within B ' + IntToStr(j+1); - title := FactorC + ' Group Codes'; + title := FactorCEdit.Text + ' Group Codes'; GraphFrm.XTitle := title; GraphFrm.YTitle := 'Mean'; GraphFrm.barwideprop := 0.5; @@ -978,18 +1232,22 @@ begin GraphFrm.WallColor := clDkGray; GraphFrm.FloorColor := clLtGray; GraphFrm.ShowBackWall := true; -// GraphFrm.ShowModal; + GraphFrm.ShowModal; end; GraphFrm.Xpoints := nil; GraphFrm.Ypoints := nil; XValue := nil; - end; +end; +{$ENDIF} procedure TABCNestedForm.UpdateBtnStates; begin inherited; - + + if FMeansReportFrame <> nil then + FMeansReportFrame.UpdateBtnStates; + AInBtn.Enabled := (VarList.ItemIndex > -1) and (FactorAEdit.Text = ''); BInBtn.Enabled := (VarList.ItemIndex > -1) and (FactorBEdit.Text = ''); CInBtn.Enabled := (VarList.ItemIndex > -1) and (FactorCEdit.Text = ''); @@ -1009,14 +1267,15 @@ begin index := VarList.ItemIndex; if index > -1 then begin s := VarList.Items[index]; - if FactorAEdit.Text = '' then + if DepEdit.Text = '' then + DepEdit.Text := s + else if FactorAEdit.Text = '' then FactorAEdit.Text := s else if FactorBEdit.Text = '' then FactorBEdit.Text := s else if FactorCEdit.Text = '' then - FactorCEdit.Text := s - else if DepEdit.Text = '' then - DepEdit.Text := s; + FactorCEdit.Text := s; + VarList.Items.Delete(index); UpdateBtnStates; end; end; diff --git a/applications/lazstats/source/forms/analysis/comparisons/axsanovaunit.lfm b/applications/lazstats/source/forms/analysis/comparisons/axsanovaunit.lfm index 7123ae824..539baf1e2 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/axsanovaunit.lfm +++ b/applications/lazstats/source/forms/analysis/comparisons/axsanovaunit.lfm @@ -226,8 +226,7 @@ inherited AxSAnovaForm: TAxSAnovaForm inherited PageControl: TPageControl Height = 397 Width = 457 - ActivePage = ReportPage - TabIndex = 0 + TabIndex = 2 inherited ReportPage: TTabSheet Caption = 'ANOVA Results' end diff --git a/applications/lazstats/source/forms/analysis/comparisons/blkanovaunit.lfm b/applications/lazstats/source/forms/analysis/comparisons/blkanovaunit.lfm index 75e3e6f94..a360ae298 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/blkanovaunit.lfm +++ b/applications/lazstats/source/forms/analysis/comparisons/blkanovaunit.lfm @@ -677,15 +677,16 @@ inherited BlksAnovaForm: TBlksAnovaForm Height = 561 Width = 485 ActivePage = PosthocPage + TabIndex = 2 inherited ReportPage: TTabSheet Caption = 'ANOVA Results' end - object PosthocPage: TTabSheet[1] + inherited ChartPage: TTabSheet + Caption = 'Plots' + end + object PosthocPage: TTabSheet[2] Caption = 'Post-Hoc' TabVisible = False end - inherited ChartPage: TTabSheet[2] - Caption = 'Plots' - end end end diff --git a/applications/lazstats/source/forms/analysis/comparisons/blkanovaunit.pas b/applications/lazstats/source/forms/analysis/comparisons/blkanovaunit.pas index 7bf5209ea..ce53eac63 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/blkanovaunit.pas +++ b/applications/lazstats/source/forms/analysis/comparisons/blkanovaunit.pas @@ -195,6 +195,8 @@ begin FStyles := TChartStyles.Create(FChartFrame); + AddComboboxToToolbar(FChartFrame.ChartToolbar, 'Plots:', FChartCombobox); + { panel := TPanel.Create(FChartFrame.ChartToolbar); lbl := TLabel.Create(panel); lbl.Parent := panel; @@ -217,7 +219,7 @@ begin panel.AutoSize := true; panel.BevelInner := bvNone; panel.BevelOuter := bvNone; - + } FChartFrame.Chart.Margins.Bottom := 0; PageControl.ActivePageIndex := 0; @@ -1538,6 +1540,11 @@ var begin inherited; + if FPostHocReportFrame <> nil then + FPostHocReportFrame.Clear; + if FChartCombobox <> nil then + FChartCombobox.Items.Clear; + VarList.Clear; for i := 1 to NoVariables do VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); diff --git a/applications/lazstats/source/units/utils.pas b/applications/lazstats/source/units/utils.pas index 9f6f4e300..3d262c353 100644 --- a/applications/lazstats/source/units/utils.pas +++ b/applications/lazstats/source/units/utils.pas @@ -5,7 +5,7 @@ unit Utils; interface uses - Classes, SysUtils, Graphics, Controls, StdCtrls, ComCtrls, Dialogs, Forms, + Classes, SysUtils, Graphics, Controls, StdCtrls, ExtCtrls, ComCtrls, Dialogs, Forms, Globals; type @@ -14,6 +14,8 @@ type procedure InitForm(AForm: TForm); procedure AddButtonToToolbar(AToolButton: TToolButton; AToolBar: TToolBar); +procedure AddComboboxToToolbar(AToolBar: TToolbar; ACaption: String; + out ACombobox: TCombobox); procedure InitToolbar(AToolbar: TToolbar; APosition: TToolbarPosition); function AnySelected(AListbox: TListBox): Boolean; @@ -44,6 +46,48 @@ begin end; +procedure AddComboboxToToolbar(AToolbar: TToolbar; ACaption: String; + out AComboBox: TComboBox); +var + panel: TPanel; + lbl: TLabel = nil; +begin + panel := TPanel.Create(AToolbar); + if ACaption <> '' then + begin + lbl := TLabel.Create(panel); + lbl.Parent := panel; + lbl.Caption := ACaption; + end; + + ACombobox := TCombobox.Create(panel); + ACombobox.Parent := panel; + ACombobox.Style := csDropdownList; + ACombobox.DropdownCount := 24; + ACombobox.Items.Clear; + ACombobox.Constraints.MinWidth := 300; + + if lbl <> nil then + begin + lbl.AnchorSideLeft.Side := asrTop; + lbl.AnchorSideLeft.Control := panel; + lbl.AnchorSideTop.Side := asrCenter; + lbl.AnchorSideTop.Control := ACombobox; + end; + + ACombobox.AnchorSideLeft.Control := lbl; + ACombobox.AnchorSideLeft.Side := asrBottom; + ACombobox.BorderSpacing.Left := 6; + ACombobox.BorderSpacing.Around := 2; + + panel.Parent := AToolbar; + panel.AutoSize := true; + panel.BevelInner := bvNone; + panel.BevelOuter := bvNone; + panel.Left := 0; +end; + + procedure InitForm(AForm: TForm); begin AForm.Width := AForm.Scale96ToFont(DEFAULT_WIDTH);