2020-03-30 18:01:44 +00:00
|
|
|
// Use file "anova2.laz" for testing
|
|
|
|
|
|
|
|
unit BlkANOVAUnit;
|
|
|
|
|
|
|
|
{$mode objfpc}{$H+}
|
2020-11-22 18:49:28 +00:00
|
|
|
{$WARN 6058 off : Call to subroutine "$1" marked as inline is not inlined}
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
2020-11-09 21:52:26 +00:00
|
|
|
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, StdCtrls, ExtCtrls,
|
|
|
|
ComCtrls, Buttons, Dialogs, LCLVersion,
|
2020-11-09 17:34:25 +00:00
|
|
|
TACustomSeries, TAStyles,
|
|
|
|
MainUnit, Globals, FunctionsLib, GraphLib,
|
|
|
|
ANOVATestsUnit, ReportFrameUnit, BasicStatsReportAndChartFormUnit;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
|
2020-11-09 17:34:25 +00:00
|
|
|
{ TBlksAnovaForm }
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-09 17:34:25 +00:00
|
|
|
TBlksAnovaForm = class(TBasicStatsReportAndChartForm)
|
2020-03-30 18:01:44 +00:00
|
|
|
Bevel1: TBevel;
|
|
|
|
BrownForsythe: TCheckBox;
|
2020-11-10 16:46:13 +00:00
|
|
|
ShowPlotsChk: TCheckBox;
|
|
|
|
Plot3dChk: TCheckBox;
|
2020-11-09 15:39:10 +00:00
|
|
|
Fact1Combo: TComboBox;
|
|
|
|
Fact2Combo: TComboBox;
|
|
|
|
Fact3Combo: TComboBox;
|
2020-11-10 16:46:13 +00:00
|
|
|
AlphaGroup: TGroupBox;
|
|
|
|
CorrectionsGroup: TGroupBox;
|
2020-11-09 15:39:10 +00:00
|
|
|
Label6: TLabel;
|
|
|
|
Label7: TLabel;
|
|
|
|
Label8: TLabel;
|
2020-11-09 17:34:25 +00:00
|
|
|
PosthocPage: TTabSheet;
|
2020-03-30 18:01:44 +00:00
|
|
|
Welch: TCheckBox;
|
|
|
|
DepIn: TBitBtn;
|
|
|
|
DepOut: TBitBtn;
|
|
|
|
Fact1In: TBitBtn;
|
|
|
|
Fact1Out: TBitBtn;
|
|
|
|
Fact2In: TBitBtn;
|
|
|
|
Fact2Out: TBitBtn;
|
|
|
|
Fact3In: TBitBtn;
|
|
|
|
Fact3Out: TBitBtn;
|
2020-11-09 17:34:25 +00:00
|
|
|
ScheffeChk: TCheckBox;
|
|
|
|
TukeyHSDChk: TCheckBox;
|
|
|
|
TukeyBChk: TCheckBox;
|
|
|
|
TukeyKramerChk: TCheckBox;
|
|
|
|
NewmanKeulsChk: TCheckBox;
|
|
|
|
BonferroniChk: TCheckBox;
|
|
|
|
OrthoContrastsChk: TCheckBox;
|
2020-11-09 15:39:10 +00:00
|
|
|
DepVarEdit: TEdit;
|
|
|
|
Factor1Edit: TEdit;
|
|
|
|
Factor2Edit: TEdit;
|
|
|
|
Factor3Edit: TEdit;
|
2020-11-09 17:34:25 +00:00
|
|
|
OverallAlphaEdit: TEdit;
|
|
|
|
PostAlphaEdit: TEdit;
|
2020-11-09 15:39:10 +00:00
|
|
|
PosthocGroup: TGroupBox;
|
2020-03-30 18:01:44 +00:00
|
|
|
Label1: TLabel;
|
|
|
|
Label3: TLabel;
|
|
|
|
Label4: TLabel;
|
|
|
|
VarList: TListBox;
|
|
|
|
StaticText1: TStaticText;
|
|
|
|
StaticText2: TStaticText;
|
|
|
|
StaticText3: TStaticText;
|
|
|
|
StaticText4: TStaticText;
|
|
|
|
procedure DepInClick(Sender: TObject);
|
|
|
|
procedure DepOutClick(Sender: TObject);
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure Plot3dChkChange(Sender: TObject);
|
|
|
|
procedure ShowPlotsChkChange(Sender: TObject);
|
2020-03-30 18:01:44 +00:00
|
|
|
procedure VarChange(Sender: TObject);
|
|
|
|
procedure Fact1OutClick(Sender: TObject);
|
|
|
|
procedure Fact2InClick(Sender: TObject);
|
|
|
|
procedure Fact2OutClick(Sender: TObject);
|
|
|
|
procedure Fact3InClick(Sender: TObject);
|
|
|
|
procedure Fact3OutClick(Sender: TObject);
|
|
|
|
procedure Fact1InClick(Sender: TObject);
|
2020-11-09 15:39:10 +00:00
|
|
|
procedure VarListDblClick(Sender: TObject);
|
2020-11-06 00:04:57 +00:00
|
|
|
procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean);
|
2020-03-30 18:01:44 +00:00
|
|
|
private
|
|
|
|
{ private declarations }
|
2020-11-10 15:11:42 +00:00
|
|
|
N: integer;
|
2020-06-23 22:10:44 +00:00
|
|
|
ColNoSelected: IntDyneVec;
|
|
|
|
SSDep, SSErr, SSF1, SSF2, SSF3, SSF1F2, SSF1F3, SSF2F3, SSF1F2F3: double;
|
|
|
|
MSDep, MSErr, MSF1, MSF2, MSF3, MSF1F2, MSF1F3, MSF2F3, MSF1F2F3: double;
|
|
|
|
DFTot, DFErr, DFF1, DFF2, DFF3, DFF1F2, DFF1F3, DFF2F3, DFF1F2F3: double;
|
|
|
|
Omega, OmegaF1, OmegaF2, OmegaF3, OmegaF1F2, F: Double;
|
|
|
|
MinSize: Double;
|
|
|
|
OmegaF1F3, OmegaF2F3, OmegaF1F2F3: double;
|
|
|
|
FF1, FF2, FF1F2, ProbF1, ProbF2, ProbF3, ProbF1F2, ProbF1F3: double;
|
|
|
|
FF3, FF2F3, FF1F3, FF1F2F3, ProbF2F3, ProbF1F2F3: double;
|
2020-11-10 16:46:13 +00:00
|
|
|
MeanDep: Double;
|
2020-11-09 15:39:10 +00:00
|
|
|
Nf1cells, Nf2cells, Nf3cells: integer;
|
2020-11-10 16:46:13 +00:00
|
|
|
MinF1, MaxF1, MinF2, MaxF2, MinF3, MaxF3, NoFactors: integer;
|
2020-11-10 15:11:42 +00:00
|
|
|
equal_grp: boolean; // check for equal groups for post-hoc tests
|
2020-06-23 22:10:44 +00:00
|
|
|
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
|
|
|
|
RowSums: DblDyneVec; // 2 way row sums
|
|
|
|
ColSums: DblDyneVec; // 2 way col sums
|
|
|
|
RowCount: IntDyneVec; // 2 way row count
|
|
|
|
ColCount: IntDyneVec; // 2 way col count
|
|
|
|
SlcSums: DblDyneVec; // 3 way slice sums
|
|
|
|
SlcCount: IntDyneVec; // 3 way slice counts
|
2020-11-10 15:11:42 +00:00
|
|
|
WSum, WX2: DblDyneCube;
|
|
|
|
NCnt: IntDyneCube;
|
2020-06-23 22:10:44 +00:00
|
|
|
NoGrpsA, NoGrpsB, NoGrpsC: integer;
|
2020-11-10 16:46:13 +00:00
|
|
|
// AllAlpha, PostHocAlpha: double; // alphas for tests
|
2020-11-10 15:11:42 +00:00
|
|
|
OKterms: array[1..14] of Boolean;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-09 17:34:25 +00:00
|
|
|
procedure Init;
|
2020-11-09 18:18:38 +00:00
|
|
|
function GetLevels(out DepValues, F1Values, F2Values, F3Values: DblDyneVec): Boolean;
|
2020-11-09 15:39:10 +00:00
|
|
|
|
2020-11-09 17:34:25 +00:00
|
|
|
procedure Init1Way;
|
|
|
|
function Calc1Way(const DepValues, F1Values: DblDyneVec): Boolean;
|
|
|
|
procedure OneWayTable;
|
|
|
|
procedure OneWayPostHoc;
|
2020-03-30 18:01:44 +00:00
|
|
|
procedure OneWayPlot;
|
2020-11-09 15:39:10 +00:00
|
|
|
|
2020-11-09 21:52:26 +00:00
|
|
|
procedure Init2Way;
|
|
|
|
function Calc2Way(const DepValues, F1Values, F2Values: DblDyneVec): Boolean;
|
|
|
|
procedure TwoWayTable;
|
2020-03-30 18:01:44 +00:00
|
|
|
procedure TwoWayPlot;
|
2020-11-09 21:52:26 +00:00
|
|
|
procedure TwoWayContrasts;
|
2020-11-09 15:39:10 +00:00
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
procedure Init3Way;
|
|
|
|
function Calc3Way(const DepValues, F1Values, F2Values, F3Values: DblDyneVec): Boolean;
|
|
|
|
procedure ThreeWayTable;
|
2020-03-30 18:01:44 +00:00
|
|
|
procedure ThreeWayPlot;
|
2020-11-10 15:11:42 +00:00
|
|
|
procedure ThreeWayContrasts;
|
2020-11-09 15:39:10 +00:00
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
procedure BrownForsytheOneWay(AReport: TStrings);
|
|
|
|
procedure WelchOneWay(AReport: TStrings);
|
|
|
|
procedure WelchtTests(AReport: TStrings);
|
|
|
|
|
2020-11-09 17:34:25 +00:00
|
|
|
private
|
|
|
|
FPosthocReportFrame: TReportFrame;
|
|
|
|
FSeries: TChartSeries;
|
|
|
|
FChartCombobox: TCombobox;
|
|
|
|
FStyles: TChartStyles;
|
2020-11-10 15:11:42 +00:00
|
|
|
procedure GetDataIndices(out ix, iy, iz: Integer);
|
2020-11-09 21:52:26 +00:00
|
|
|
procedure PopulateChartCombobox(ThreeWay: Boolean);
|
|
|
|
procedure SelectTwoWayPlot(Sender: TObject);
|
2020-11-10 15:11:42 +00:00
|
|
|
procedure SelectThreeWayPlot(Sender: TObject);
|
2020-11-09 17:34:25 +00:00
|
|
|
|
2020-11-09 15:39:10 +00:00
|
|
|
protected
|
|
|
|
procedure AdjustConstraints; override;
|
|
|
|
procedure Compute; override;
|
|
|
|
procedure UpdateBtnStates; override;
|
|
|
|
function Validate(out AMsg: String; out AControl: TWinControl): Boolean; override;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
public
|
2020-11-09 15:39:10 +00:00
|
|
|
constructor Create(AOwner: TComponent); override;
|
|
|
|
procedure Reset; override;
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
var
|
2020-11-09 17:34:25 +00:00
|
|
|
BlksAnovaForm: TBlksAnovaForm;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
implementation
|
|
|
|
|
2020-11-09 15:39:10 +00:00
|
|
|
{$R *.lfm}
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
uses
|
2020-09-28 14:05:34 +00:00
|
|
|
Math,
|
2020-11-09 21:52:26 +00:00
|
|
|
TAChartUtils, TACustomSource, TASeries, TALegend,
|
2020-11-09 17:34:25 +00:00
|
|
|
Utils, MathUnit, MatrixUnit, ChartFrameUnit, GridProcs;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
const
|
|
|
|
FIXED_RANDOM: array[0..1] of string = ('fixed', 'random');
|
|
|
|
|
|
|
|
|
2020-11-09 17:34:25 +00:00
|
|
|
{ TBlksAnovaForm }
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-09 17:34:25 +00:00
|
|
|
constructor TBlksAnovaForm.Create(AOwner: TComponent);
|
2020-11-09 15:39:10 +00:00
|
|
|
begin
|
|
|
|
inherited;
|
|
|
|
|
|
|
|
if GraphFrm = nil then
|
|
|
|
Application.CreateForm(TGraphFrm, GraphFrm);
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
PostAlphaEdit.Text := FormatFloat('0.00', DEFAULT_ALPHA_LEVEL);
|
|
|
|
OverallAlphaEdit.Text := FormatFloat('0.00', DEFAULT_ALPHA_LEVEL);
|
2020-11-09 17:34:25 +00:00
|
|
|
|
|
|
|
FPosthocReportFrame := TReportFrame.Create(PostHocPage);
|
|
|
|
FPosthocReportFrame.Parent := PostHocPage;
|
|
|
|
FPosthocReportFrame.Align := alClient;
|
|
|
|
InitToolbar(FPosthocReportFrame.ReportToolbar, tpTop);
|
|
|
|
PostHocPage.PageIndex := 1;
|
|
|
|
|
|
|
|
FStyles := TChartStyles.Create(FChartFrame);
|
|
|
|
|
2020-11-12 18:31:56 +00:00
|
|
|
AddComboboxToToolbar(FChartFrame.ChartToolbar, 'Plots:', FChartCombobox);
|
2020-11-09 17:34:25 +00:00
|
|
|
FChartFrame.Chart.Margins.Bottom := 0;
|
|
|
|
|
|
|
|
PageControl.ActivePageIndex := 0;
|
2020-11-09 15:39:10 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-11-09 17:34:25 +00:00
|
|
|
procedure TBlksAnovaForm.AdjustConstraints;
|
2020-11-09 15:39:10 +00:00
|
|
|
begin
|
|
|
|
inherited;
|
|
|
|
ParamsPanel.Constraints.MinHeight := Fact3Combo.Top + Fact3Combo.Height +
|
2020-11-10 16:46:13 +00:00
|
|
|
VarList.BorderSpacing.Bottom +
|
|
|
|
CorrectionsGroup.Height + CorrectionsGroup.BorderSpacing.Bottom +
|
|
|
|
AlphaGroup.Height +
|
|
|
|
ShowPlotsChk.BorderSpacing.Top + ShowPlotsChk.Height +
|
2020-11-09 15:39:10 +00:00
|
|
|
ButtonBevel.Height + CloseBtn.BorderSpacing.Top + CloseBtn.Height;
|
|
|
|
ParamsPanel.Constraints.MinWidth := Max(
|
2020-11-10 16:46:13 +00:00
|
|
|
CorrectionsGroup.Width * 2 + Bevel1.Width,
|
2020-11-09 15:39:10 +00:00
|
|
|
4*CloseBtn.Width + 3*CloseBtn.BorderSpacing.Left
|
|
|
|
);
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.BrownForsytheOneWay(AReport: TStrings);
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-11-10 16:46:13 +00:00
|
|
|
i, intValue: integer;
|
|
|
|
c1: array[1..50] of double;
|
|
|
|
cellmeans: array[1..50] of double;
|
|
|
|
sumc1: double;
|
|
|
|
fdegfree: double;
|
|
|
|
Fnumerator, Fdenominator, NewF: double;
|
|
|
|
X, Xsq: Double;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
for i := 1 to 50 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
c1[i] := 0.0;
|
|
|
|
cellmeans[i] := 0.0;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
for i := 1 to NoCases do
|
|
|
|
begin
|
|
|
|
if not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected) then continue;
|
|
|
|
intvalue := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[1], i]))) - MinF1;
|
|
|
|
cellcnts[intvalue] := 0;
|
|
|
|
cellsums[intvalue] := 0.0;
|
|
|
|
cellvars[intvalue] := 0.0;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
MeanDep := 0.0;
|
|
|
|
SSDep := 0.0;
|
|
|
|
SSF1 := 0.0;
|
|
|
|
MSErr := 0.0;
|
|
|
|
N := 0;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
for i := 1 to NoCases do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
if not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected) then continue;
|
|
|
|
intvalue := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[1], i]))) - MinF1;
|
|
|
|
X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[0], i]));
|
|
|
|
Xsq := X*X;
|
|
|
|
cellcnts[intvalue] := cellcnts[intvalue] + 1;
|
|
|
|
cellsums[intvalue] := cellsums[intvalue] + X;
|
|
|
|
cellvars[intvalue] := cellvars[intvalue] + Xsq;
|
|
|
|
MeanDep := MeanDep + X;
|
|
|
|
SSDep := SSDep + Xsq;
|
|
|
|
N := N + 1;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
DFF1 := 0;
|
|
|
|
for i := 0 to Nf1cells-1 do
|
|
|
|
begin
|
|
|
|
if cellcnts[i] > 0 then
|
|
|
|
begin
|
|
|
|
cellvars[i] := (cellvars[i] - sqr(cellsums[i]) /cellcnts[i]) / (cellcnts[i] - 1);
|
|
|
|
SSF1 := SSF1 + (sqr(cellsums[i]) / cellcnts[i]);
|
|
|
|
DFF1 := DFF1 + 1;
|
|
|
|
end;
|
|
|
|
end;
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
SSF1 := SSF1 - (sqr(MeanDep) / N);
|
|
|
|
SSDep := SSDep - (sqr(MeanDep) / N);
|
|
|
|
SSErr := SSDep - SSF1;
|
|
|
|
DFTot := N - 1;
|
|
|
|
DFF1 := DFF1 - 1;
|
|
|
|
DFErr := DFTot - DFF1;
|
|
|
|
MSF1 := SSF1 / DFF1;
|
|
|
|
MSErr := SSErr / DFErr;
|
|
|
|
MSDep := SSDep / DFTot;
|
|
|
|
Omega := (SSF1 - DFF1 * MSErr) / (SSDep + MSErr);
|
|
|
|
F := MSF1 / MSErr;
|
|
|
|
ProbF1 := probf(F,DFF1,DFErr);
|
|
|
|
MeanDep := MeanDep / N;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
AReport.Add('');
|
|
|
|
AReport.Add('');
|
|
|
|
AReport.Add(DIVIDER);
|
|
|
|
AReport.Add('BROWN-FORSYTHE ONE WAY ANALYSIS OF VARIANCE RESULTS');
|
|
|
|
AReport.Add('');
|
|
|
|
AReport.Add('Dependent variable is: %s, Independent variable is: %s', [DepVarEdit.Text, Factor1Edit.Text]);
|
|
|
|
AReport.Add('');
|
|
|
|
AReport.Add('Traditional One-Way ANOVA Results');
|
|
|
|
AReport.Add(DIVIDER_SMALL);
|
|
|
|
AReport.Add('SOURCE D.F. SS MS F PROB.>F OMEGA SQR.');
|
|
|
|
AReport.Add('-----------------------------------------------------------------------');
|
|
|
|
AReport.Add('BETWEEN %4.0f%10.2f%10.2f%10.2f%10.2f%10.2f', [DFF1, SSF1, MSF1, F, ProbF1, Omega]);
|
|
|
|
AReport.Add('WITHIN %4.0f%10.2f%10.2f', [DFErr, SSErr, MSErr]);
|
|
|
|
AReport.Add('TOTAL %4.0f%10.2f', [DFTot, SSDep]);
|
|
|
|
AReport.Add(DIVIDER);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
sumc1 := 0.0;
|
|
|
|
MSErr := 0.0;
|
|
|
|
for i := 0 to Nf1cells-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
c1[i+1] := (1.0 - (cellcnts[i] / N)) * cellvars[i];
|
|
|
|
sumc1 := sumc1 + c1[i+1];
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
for i := 1 to Nf1cells do
|
|
|
|
c1[i] := c1[i] / sumc1;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
fdegfree := 0.0;
|
|
|
|
for i := 1 to Nf1cells do
|
|
|
|
fdegfree := fdegfree + ((c1[i] * c1[i]) / (cellcnts[i-1]-1.0));
|
|
|
|
fdegfree := round(1.0 / fdegfree);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
Fnumerator := 0.0;
|
|
|
|
Fdenominator := 0.0;
|
|
|
|
for i := 1 to Nf1cells do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
cellmeans[i] := cellsums[i-1] / cellcnts[i-1];
|
|
|
|
FNumerator := FNumerator + (cellcnts[i-1] * (sqr(cellmeans[i] - MeanDep)));
|
|
|
|
FDenominator := FDenominator + ((1.0 - (cellcnts[i-1] / N)) * cellvars[i-1]);
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
NewF := FNumerator / FDenominator;
|
|
|
|
ProbF1 := probf(NewF,DFF1, fdegfree);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
AReport.Add('');
|
|
|
|
AReport.Add(DIVIDER);
|
|
|
|
AReport.Add('Brown-Forsythe F statistic: %8.3f', [NewF]);
|
|
|
|
AReport.Add('Brown-Forsythe denominator degrees of freedom: %8.0f', [fdegfree]);
|
|
|
|
AReport.Add('Brown-Forsythe F probability: %8.3f', [probf1]);
|
|
|
|
AReport.Add(DIVIDER);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
WelchtTests(AReport);
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
function TBlksAnovaForm.Calc1Way(const DepValues, F1Values: DblDyneVec): Boolean;
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-11-10 16:46:13 +00:00
|
|
|
i, j: integer;
|
|
|
|
X, Xsq: Double;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
// Get working totals
|
|
|
|
N := 0;
|
|
|
|
MeanDep := 0;
|
|
|
|
SSDep := 0;
|
|
|
|
for i := 0 to High(DepValues) do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
j := round(F1Values[i]) - MinF1;
|
|
|
|
X := DepValues[i];
|
|
|
|
Xsq := X * X;
|
|
|
|
cellCnts[j] := cellCnts[j] + 1;
|
|
|
|
cellSums[j] := cellSums[j] + X;
|
|
|
|
cellVars[j] := CellVars[j] + Xsq;
|
|
|
|
MeanDep := MeanDep + X;
|
|
|
|
SSDep := SSDep + Xsq;
|
|
|
|
N := N + 1;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
DFF1 := 0;
|
|
|
|
SSF1 := 0;
|
|
|
|
for i := 0 to NF1Cells-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
if cellCnts[i] > 0 then
|
|
|
|
begin
|
|
|
|
SSF1 := SSF1 + sqr(cellSums[i]) / cellCnts[i];
|
|
|
|
DFF1 := DFF1 + 1;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-11-09 17:34:25 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
SSF1 := SSF1 - sqr(MeanDep) / N;
|
|
|
|
SSDep := SSDep - sqr(MeanDep) / N;
|
|
|
|
SSErr := SSDep - SSF1;
|
2020-11-09 17:34:25 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
DFTot := N - 1;
|
|
|
|
DFF1 := DFF1 - 1;
|
|
|
|
DFErr := DFTot - DFF1;
|
2020-11-09 17:34:25 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
MSF1 := SSF1 / DFF1;
|
|
|
|
MSErr := SSErr / DFErr;
|
|
|
|
MSDep := SSDep / DFTot;
|
2020-11-09 17:34:25 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
Omega := (SSF1 - DFF1 * MSErr) / (SSDep + MSErr);
|
|
|
|
F := MSF1 / MSErr;
|
|
|
|
ProbF1 := ProbF(F, DFF1, DFErr);
|
|
|
|
MeanDep := MeanDep / N;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-09 18:18:38 +00:00
|
|
|
Result := true;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-09 17:34:25 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
function TBlksAnovaForm.Calc2Way(const DepValues, F1Values, F2Values: DblDyneVec): Boolean;
|
2020-11-09 17:34:25 +00:00
|
|
|
var
|
|
|
|
i, j: integer;
|
2020-11-10 16:46:13 +00:00
|
|
|
grpA, grpB: integer;
|
|
|
|
constant, rowsTotCnt, colsTotCnt, SSCells: double;
|
2020-11-09 17:34:25 +00:00
|
|
|
X, Xsq: Double;
|
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
// initialize matrix values
|
|
|
|
NoGrpsA := MaxF1 - MinF1 + 1;
|
|
|
|
NoGrpsB := MaxF2 - MinF2 + 1;
|
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
// Get working totals
|
2020-11-09 17:34:25 +00:00
|
|
|
N := 0;
|
2020-11-10 16:46:13 +00:00
|
|
|
MeanDep := 0.0;
|
|
|
|
SSDep := 0.0;
|
|
|
|
SSCells := 0.0;
|
2020-11-09 17:34:25 +00:00
|
|
|
for i := 0 to High(DepValues) do
|
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
grpA := round(F1Values[i]) - MinF1;
|
|
|
|
grpB := round(F2Values[i]) - MinF2;
|
2020-11-09 17:34:25 +00:00
|
|
|
X := DepValues[i];
|
|
|
|
Xsq := X * X;
|
2020-11-10 16:46:13 +00:00
|
|
|
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;
|
|
|
|
ColSums[grpB] := ColSums[grpB] + X;
|
|
|
|
RowCount[grpA] := RowCount[grpA] + 1;
|
|
|
|
ColCount[grpB] := ColCount[grpB] + 1;
|
2020-03-30 18:01:44 +00:00
|
|
|
MeanDep := MeanDep + X;
|
2020-11-09 17:34:25 +00:00
|
|
|
SSDep := SSDep + Xsq;
|
2020-03-30 18:01:44 +00:00
|
|
|
N := N + 1;
|
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Calculate results
|
2020-11-09 17:34:25 +00:00
|
|
|
SSF1 := 0;
|
2020-11-10 16:46:13 +00:00
|
|
|
RowsTotCnt := 0;
|
|
|
|
for i := 0 to NoGrpsA-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
SSF1 := SSF1 + sqr(RowSums[i]) / RowCount[i];
|
|
|
|
RowsTotCnt := RowsTotCnt + RowCount[i];
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
SSF2 := 0;
|
|
|
|
ColsTotCnt := 0;
|
|
|
|
for j := 0 to NoGrpsB-1 do
|
|
|
|
begin
|
|
|
|
SSF2 := SSF2 + sqr(ColSums[j]) / ColCount[j];
|
|
|
|
ColsTotCnt := ColsTotCnt + ColCount[j];
|
|
|
|
end;
|
|
|
|
|
|
|
|
SSCells := 0;
|
|
|
|
for i := 0 to NoGrpsA-1 do
|
|
|
|
for j := 0 to NoGrpsB-1 do
|
|
|
|
if Counts[i, j] > 0 then
|
|
|
|
SSCells := SSCells + sqr(sums[i, j]) / Counts[i, j];
|
|
|
|
|
|
|
|
if N > 0 then
|
|
|
|
constant := sqr(MeanDep) / N
|
|
|
|
else
|
|
|
|
constant := 0.0;
|
|
|
|
|
|
|
|
SSF1 := SSF1 - constant;
|
|
|
|
SSF2 := SSF2 - constant;
|
|
|
|
SSF1F2 := SSCells - SSF1 - SSF2 - constant;
|
|
|
|
SSErr := SSDep - SSCells;
|
|
|
|
SSDep := SSDep - constant; // Must be after SSErr!
|
|
|
|
|
|
|
|
if (SSF1F2 < 0) or (SSF1 < 0) or (SSF2 < 0) then
|
|
|
|
begin
|
|
|
|
ErrorMsg('A negative SS found. Unbalanced design? Ending analysis.');
|
|
|
|
Result := false;
|
|
|
|
exit;
|
|
|
|
end;
|
2020-11-09 17:34:25 +00:00
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
DFTot := N - 1;
|
2020-11-10 16:46:13 +00:00
|
|
|
DFF1 := NoGrpsA - 1;
|
|
|
|
DFF2 := NoGrpsB - 1;
|
|
|
|
DFF1F2 := DFF1 * DFF2;
|
|
|
|
DFErr := DFTot - DFF1 - DFF2 - DFF1F2;
|
2020-11-09 17:34:25 +00:00
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
MSF1 := SSF1 / DFF1;
|
2020-11-10 16:46:13 +00:00
|
|
|
MSF2 := SSF2 / DFF2;
|
|
|
|
MSF1F2 := SSF1F2 / DFF1F2;
|
2020-03-30 18:01:44 +00:00
|
|
|
MSErr := SSErr / DFErr;
|
|
|
|
MSDep := SSDep / DFTot;
|
2020-11-09 17:34:25 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
OmegaF1 := (SSF1 - DFF1 * MSErr) / (SSDep + MSErr);
|
|
|
|
OmegaF2 := (SSF2 - DFF2 * MSErr) / (SSDep + MSErr);
|
|
|
|
OmegaF1F2 := (SSF1F2 - DFF1F2 * MSErr) / (SSDep + MSErr);
|
|
|
|
Omega := OmegaF1 + OmegaF2 + OmegaF1F2;
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
MeanDep := MeanDep / N;
|
2020-11-09 17:34:25 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// F tests for fixed effects
|
|
|
|
if (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 0) then
|
|
|
|
begin
|
|
|
|
FF1 := abs(MSF1 / MSErr);
|
|
|
|
FF2 := abs(MSF2 / MSErr);
|
|
|
|
FF1F2 := abs(MSF1F2 / MSErr);
|
|
|
|
ProbF1 := ProbF(FF1, DFF1, DFErr);
|
|
|
|
ProbF2 := ProbF(FF2, DFF2, DFErr);
|
|
|
|
ProbF1F2 := ProbF(FF1F2, DFF1F2, DFErr);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
// F tests if both factors are random
|
|
|
|
if (Fact1Combo.ItemIndex = 1) and (Fact2Combo.ItemIndex = 1) then
|
|
|
|
begin
|
|
|
|
FF1 := abs(MSF1 / MSF1F2);
|
|
|
|
FF2 := abs(MSF2 / MSF1F2);
|
|
|
|
FF1F2 := abs(MSF1F2 / MSErr);
|
|
|
|
ProbF1 := ProbF(FF1, DFF1, DFF1F2);
|
|
|
|
ProbF2 := ProbF(FF2, DFF2, DFF1F2);
|
|
|
|
ProbF3 := ProbF(FF1F2, DFF1F2, DFErr);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
// F test if factor A is random and factor B is fixed
|
|
|
|
if (Fact1Combo.ItemIndex = 1) and (Fact2Combo.ItemIndex = 0) then
|
|
|
|
begin
|
|
|
|
FF1 := abs(MSF1 / MSErr);
|
|
|
|
FF2 := abs(MSF2 / MSF1F2);
|
|
|
|
FF1F2 := abs(MSF1F2 / MSErr);
|
|
|
|
ProbF1 := ProbF(FF1, DFF1, DFErr);
|
|
|
|
ProbF2 := ProbF(FF2, DFF2, DFF1F2);
|
|
|
|
ProbF3 := ProbF(FF1F2, DFF1F2, DFErr);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
// F test if factor A is fixed and factor B is random
|
|
|
|
if (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 1) then
|
|
|
|
begin
|
|
|
|
FF1 := abs(MSF1 / MSF1F2);
|
|
|
|
FF2 := abs(MSF2 / MSErr);
|
|
|
|
FF1F2 := abs(MSF1F2 / MSErr);
|
|
|
|
ProbF1 := ProbF(FF1, DFF1, DFF1F2);
|
|
|
|
ProbF2 := ProbF(FF2, DFF2, DFErr);
|
|
|
|
ProbF3 := ProbF(FF1F2, DFF1F2, DFErr);
|
|
|
|
end;
|
|
|
|
|
|
|
|
if (ProbF1 > 1.0) then ProbF1 := 1.0;
|
|
|
|
if (ProbF2 > 1.0) then ProbF2 := 1.0;
|
|
|
|
if (ProbF1F2 > 1.0) then ProbF1F2 := 1.0;
|
|
|
|
|
|
|
|
// Obtain omega squared (proportion of dependent variable explained)
|
|
|
|
if (OmegaF1 < 0.0) then OmegaF1 := 0.0;
|
|
|
|
if (OmegaF2 < 0.0) then OmegaF2 := 0.0;
|
|
|
|
if (OmegaF1F2 < 0.0) then OmegaF1F2 := 0.0;
|
|
|
|
if (Omega < 0.0) then Omega := 0.0;
|
|
|
|
|
2020-11-09 17:34:25 +00:00
|
|
|
Result := true;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
|
|
|
|
function TBlksAnovaForm.Calc3Way(const DepValues, F1Values, F2Values, F3Values: DblDyneVec): Boolean;
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-11-10 16:46:13 +00:00
|
|
|
i, j, k: integer;
|
|
|
|
grpA, grpB, grpC: integer;
|
|
|
|
Constant, RowsTotCnt, ColsTotCnt, SlcsTotCnt, SSCells: double;
|
|
|
|
p, n2: double;
|
2020-11-09 21:52:26 +00:00
|
|
|
X, Xsq: Double;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-09 21:52:26 +00:00
|
|
|
NoGrpsA := MaxF1 - MinF1 + 1;
|
|
|
|
NoGrpsB := MaxF2 - MinF2 + 1;
|
2020-11-10 16:46:13 +00:00
|
|
|
NoGrpsC := MaxF3 - MinF3 + 1;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-09 21:52:26 +00:00
|
|
|
// Get working totals
|
2020-06-23 18:16:25 +00:00
|
|
|
N := 0;
|
2020-11-10 16:46:13 +00:00
|
|
|
MeanDep := 0;
|
|
|
|
SSDep := 0;
|
2020-11-09 21:52:26 +00:00
|
|
|
for i := 0 to High(DepValues) do
|
2020-06-23 18:16:25 +00:00
|
|
|
begin
|
2020-11-09 21:52:26 +00:00
|
|
|
grpA := round(F1Values[i]) - MinF1;
|
|
|
|
grpB := round(F2Values[i]) - MinF2;
|
2020-11-10 16:46:13 +00:00
|
|
|
grpC := round(F3Values[i]) - MinF3;
|
2020-11-09 21:52:26 +00:00
|
|
|
X := DepValues[i];
|
|
|
|
Xsq := X * X;
|
2020-11-10 16:46:13 +00:00
|
|
|
NCnt[grpA, grpB, grpC] := NCnt[grpA, grpB, grpC] + 1;
|
|
|
|
WSum[grpA, grpB, grpC] := WSum[grpA, grpB, grpc] + X;
|
|
|
|
WX2[grpA, grpB, grpC] := WX2[grpA, grpB, grpC] + Xsq;
|
2020-11-09 21:52:26 +00:00
|
|
|
RowSums[grpA] := RowSums[grpA] + X;
|
|
|
|
ColSums[grpB] := ColSums[grpB] + X;
|
2020-11-10 16:46:13 +00:00
|
|
|
SlcSums[grpC] := SlcSums[grpC] + X;
|
2020-11-09 21:52:26 +00:00
|
|
|
RowCount[grpA] := RowCount[grpA] + 1;
|
|
|
|
ColCount[grpB] := ColCount[grpB] + 1;
|
2020-11-10 16:46:13 +00:00
|
|
|
SlcCount[grpC] := SlcCount[grpC] + 1;
|
2020-11-09 21:52:26 +00:00
|
|
|
MeanDep := MeanDep + X;
|
|
|
|
SSDep := SSDep + Xsq;
|
|
|
|
N := N + 1;
|
2020-06-23 18:16:25 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
// Calculate results
|
2020-11-10 16:46:13 +00:00
|
|
|
constant := sqr(MeanDep) / N;
|
|
|
|
|
|
|
|
// Get SS for rows
|
2020-11-09 21:52:26 +00:00
|
|
|
SSF1 := 0;
|
|
|
|
RowsTotCnt := 0;
|
2020-06-23 18:16:25 +00:00
|
|
|
for i := 0 to NoGrpsA-1 do
|
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
SSF1 := SSF1 + sqr(RowSums[i]) / RowCount[i];
|
2020-06-23 18:16:25 +00:00
|
|
|
RowsTotCnt := RowsTotCnt + RowCount[i];
|
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
SSF1 := SSF1 - constant;
|
2020-06-23 18:16:25 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Get SS for columns
|
2020-11-09 21:52:26 +00:00
|
|
|
SSF2 := 0;
|
|
|
|
ColsTotCnt := 0;
|
2020-06-23 18:16:25 +00:00
|
|
|
for j := 0 to NoGrpsB-1 do
|
|
|
|
begin
|
2020-11-09 21:52:26 +00:00
|
|
|
SSF2 := SSF2 + sqr(ColSums[j]) / ColCount[j];
|
2020-06-23 18:16:25 +00:00
|
|
|
ColsTotCnt := ColsTotCnt + ColCount[j];
|
|
|
|
end;
|
2020-11-09 21:52:26 +00:00
|
|
|
SSF2 := SSF2 - constant;
|
2020-06-23 18:16:25 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Get SS for slices
|
|
|
|
SSF3 := 0;
|
|
|
|
SlcsTotCnt := 0;
|
|
|
|
for k := 0 to NoGrpsC-1 do
|
2020-06-23 18:16:25 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
SSF3 := SSF3 + sqr(SlcSums[k]) / SlcCount[k];
|
|
|
|
SlcsTotCnt := SlcsTotCnt + SlcCount[k];
|
|
|
|
end;
|
|
|
|
SSF3 := SSF3 - constant;
|
|
|
|
|
|
|
|
// Get SS for row-col interaction
|
|
|
|
SSF1F2 := 0;
|
|
|
|
for i := 0 to NoGrpsA-1 do
|
|
|
|
begin
|
|
|
|
for j := 0 to NoGrpsB-1 do
|
|
|
|
begin
|
|
|
|
p := 0.0;
|
|
|
|
n2 := 0.0;
|
|
|
|
for k := 0 to NoGrpsC-1 do
|
|
|
|
begin
|
|
|
|
p := p + WSum[i, j, k];
|
|
|
|
n2 := n2 + NCnt[i, j, k];
|
|
|
|
end;
|
|
|
|
SSF1F2 := SSF1F2 + sqr(p) / n2;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
SSF1F2 := SSF1F2 - SSF1 - SSF2 - constant;
|
|
|
|
|
|
|
|
// Get SS for row-slice interaction
|
|
|
|
SSF1F3 := 0;
|
|
|
|
for i := 0 to NoGrpsA-1 do
|
|
|
|
begin
|
|
|
|
for k := 0 to NoGrpsC-1 do
|
|
|
|
begin
|
|
|
|
p := 0.0;
|
|
|
|
n2 := 0.0;
|
|
|
|
for j := 0 to NoGrpsB-1 do
|
|
|
|
begin
|
|
|
|
p := p + WSum[i, j, k];
|
|
|
|
n2 := n2 + NCnt[i, j, k];
|
|
|
|
end;
|
|
|
|
SSF1F3 := SSF1F3 + sqr(p) / n2;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
SSF1F3 := SSF1F3 - SSF1 - SSF3 - constant;
|
|
|
|
|
|
|
|
// Get SS for column-slice interaction
|
|
|
|
SSF2F3 := 0;
|
|
|
|
for j := 0 to NoGrpsB-1 do
|
|
|
|
begin
|
|
|
|
for k := 0 to NoGrpsC-1 do
|
|
|
|
begin
|
|
|
|
p := 0.0;
|
|
|
|
n2 := 0.0;
|
|
|
|
for i := 0 to NoGrpsA-1 do
|
|
|
|
begin
|
|
|
|
p := p + WSum[i, j, k];
|
|
|
|
n2 := n2 + NCnt[i, j, k];
|
|
|
|
end;
|
|
|
|
SSF2F3 := SSF2F3 + sqr(p) / n2;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
SSF2F3 := SSF2F3 - SSF2 - SSF3 - constant;
|
|
|
|
|
|
|
|
// Get SS for cells
|
|
|
|
SSCells := 0;
|
|
|
|
for i := 0 to NoGrpsA-1 do
|
|
|
|
for j := 0 to NoGrpsB-1 do
|
|
|
|
for k := 0 to NoGrpsC-1 do
|
|
|
|
SSCells := SSCells + sqr(wsum[i, j, k]) / ncnt[i, j, k];
|
|
|
|
|
|
|
|
SSF1F2F3 := SSCells - SSF1 - SSF2 - SSF3 - SSF1F2 - SSF1F3 - SSF2F3 - constant;
|
|
|
|
SSErr := SSDep - SSCells;
|
|
|
|
SSDep := SSDep - constant;
|
|
|
|
|
|
|
|
if (SSF1 < 0.0) or (SSF2 < 0.0) or (SSF3 < 0.0) or
|
|
|
|
(SSF1F2 < 0.0) or (SSF1F3 < 0.0) or (SSF2F3 < 0.0) or
|
|
|
|
(SSF1F2F3 < 0.0) then
|
|
|
|
begin
|
|
|
|
ErrorMsg('A negative SS found. Unbalanced Design? Ending analysis.');
|
|
|
|
Result := false;
|
|
|
|
exit;
|
2020-06-23 18:16:25 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
DFTot := N - 1;
|
|
|
|
DFF1 := NoGrpsA - 1;
|
|
|
|
DFF2 := NoGrpsB - 1;
|
2020-11-10 16:46:13 +00:00
|
|
|
DFF3 := NoGrpsC - 1;
|
2020-06-23 18:16:25 +00:00
|
|
|
DFF1F2 := DFF1 * DFF2;
|
2020-11-10 16:46:13 +00:00
|
|
|
DFF1F3 := DFF1 * DFF3;
|
|
|
|
DFF2F3 := DFF2 * DFF3;
|
|
|
|
DFF1F2F3 := DFF1 * DFF2 * DFF3;
|
|
|
|
DFErr := DFTot - DFF1 - DFF2 - DFF3 - DFF1F2 - DFF1F3 - DFF2F3 - DFF1F2F3;
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-06-23 18:16:25 +00:00
|
|
|
MSF1 := SSF1 / DFF1;
|
|
|
|
MSF2 := SSF2 / DFF2;
|
2020-11-10 16:46:13 +00:00
|
|
|
MSF3 := SSF3 / DFF3;
|
2020-06-23 18:16:25 +00:00
|
|
|
MSF1F2 := SSF1F2 / DFF1F2;
|
2020-11-10 16:46:13 +00:00
|
|
|
MSF1F3 := SSF1F3 / DFF1F3;
|
|
|
|
MSF2F3 := SSF2F3 / DFF2F3;
|
|
|
|
MSF1F2F3 := SSF1F2F3 / DFF1F2F3;
|
2020-06-23 18:16:25 +00:00
|
|
|
MSErr := SSErr / DFErr;
|
|
|
|
MSDep := SSDep / DFTot;
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-06-23 18:16:25 +00:00
|
|
|
OmegaF1 := (SSF1 - DFF1 * MSErr) / (SSDep + MSErr);
|
|
|
|
OmegaF2 := (SSF2 - DFF2 * MSErr) / (SSDep + MSErr);
|
2020-11-10 16:46:13 +00:00
|
|
|
OmegaF3 := (SSF3 - DFF3 * MSErr) / (SSDep + MSErr);
|
2020-06-23 18:16:25 +00:00
|
|
|
OmegaF1F2 := (SSF1F2 - DFF1F2 * MSErr) / (SSDep + MSErr);
|
2020-11-10 16:46:13 +00:00
|
|
|
OmegaF1F3 := (SSF1F3 - DFF1F3 * MSErr) / (SSDep + MSErr);
|
|
|
|
OmegaF2F3 := (SSF2F3 - DFF2F3 * MSErr) / (SSDep + MSErr);
|
|
|
|
OmegaF1F2F3 := (SSF1F2F3 - DFF1F2F3 * MSErr) / (SSDep + MSErr);
|
|
|
|
Omega := OmegaF1 + OmegaF2 + OmegaF3 + OmegaF1F2 + OmegaF1F3 + OmegaF2F3 + OmegaF1F2F3;
|
2020-06-23 18:16:25 +00:00
|
|
|
MeanDep := MeanDep / N;
|
|
|
|
|
|
|
|
// F tests for fixed effects
|
2020-11-10 16:46:13 +00:00
|
|
|
if (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 0) and (Fact3Combo.ItemIndex = 0) then
|
2020-06-23 18:16:25 +00:00
|
|
|
begin
|
|
|
|
FF1 := abs(MSF1 / MSErr);
|
|
|
|
FF2 := abs(MSF2 / MSErr);
|
2020-11-10 16:46:13 +00:00
|
|
|
FF3 := abs(MSF3 / MSErr);
|
2020-06-23 18:16:25 +00:00
|
|
|
FF1F2 := abs(MSF1F2 / MSErr);
|
2020-11-10 16:46:13 +00:00
|
|
|
FF1F3 := abs(MSF1F3 / MSErr);
|
|
|
|
FF2F3 := abs(MSF2F3 / MSErr);
|
|
|
|
FF1F2F3 := abs(MSF1F2F3 / MSErr);
|
2020-11-09 21:52:26 +00:00
|
|
|
ProbF1 := ProbF(FF1, DFF1, DFErr);
|
|
|
|
ProbF2 := ProbF(FF2, DFF2, DFErr);
|
2020-11-10 16:46:13 +00:00
|
|
|
ProbF3 := ProbF(FF3, DFF3, DFErr);
|
2020-11-09 21:52:26 +00:00
|
|
|
ProbF1F2 := ProbF(FF1F2, DFF1F2, DFErr);
|
2020-11-10 16:46:13 +00:00
|
|
|
ProbF1F3 := ProbF(FF1F3, DFF1F3, DFErr);
|
|
|
|
ProbF2F3 := ProbF(FF2F3, DFF2F3, DFErr);
|
|
|
|
ProbF1F2F3 := ProbF(FF1F2F3, DFF1F2F3, DFErr);
|
|
|
|
end;
|
|
|
|
|
|
|
|
// F tests if all factors are random
|
|
|
|
for i := 1 to 14 do OKterms[i] := true; // initialize as OK
|
|
|
|
|
|
|
|
if (Fact1Combo.ItemIndex = 1) and (Fact2Combo.ItemIndex = 1) and (Fact3Combo.ItemIndex = 1) then
|
2020-06-23 18:16:25 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
if (MSF1F2 + MSF1F3 - MSF1F2F3) <= 0.0
|
|
|
|
then OKTerms[1] := false
|
|
|
|
else FF1 := abs(MSF1 / (MSF1F2 + MSF1F3 - MSF1F2F3));
|
|
|
|
if (MSF1F2 + MSF2F3 - MSF1F2F3) <= 0.0
|
|
|
|
then OKTerms[2] := false
|
|
|
|
else FF2 := abs(MSF2 / (MSF1F2 + MSF2F3 - MSF1F2F3));
|
|
|
|
if (MSF1F3 + MSF2F3 - MSF1F2F3) <= 0.0
|
|
|
|
then OKTerms[3] := false
|
|
|
|
else FF3 := abs(MSF3 / (MSF1F3 + MSF2F3 - MSF1F2F3));
|
|
|
|
FF1F2 := abs(MSF1F2 / MSF1F2F3);
|
|
|
|
FF1F3 := abs(MSF1F3 / MSF1F2F3);
|
|
|
|
FF2F3 := abs(MSF2F3 / MSF1F2F3);
|
|
|
|
FF1F2F3 := abs(MSF1F2F3 / MSErr);
|
|
|
|
ProbF1 := ProbF(FF1, DFF1, DFF1F2F3);
|
|
|
|
ProbF2 := ProbF(FF2, DFF2, DFF1F2F3);
|
|
|
|
ProbF3 := ProbF(FF3, DFF3, DFF1F2F3);
|
|
|
|
ProbF1F2 := ProbF(FF1F2, DFF1F2, DFF1F2F3);
|
|
|
|
probF1F3 := ProbF(FF1F3, DFF1F3, DFF1F2F3);
|
|
|
|
probF2F3 := ProbF(FF2F3, DFF2F3, DFF1F2F3);
|
|
|
|
probF1F2F3 := ProbF(FF1F2F3, DFF1F2F3, DFErr);
|
|
|
|
end;
|
|
|
|
|
|
|
|
// F test if factor A is random, B and C Fixed
|
|
|
|
if (Fact1Combo.ItemIndex = 1) and (Fact2Combo.ItemIndex = 0) and (Fact3Combo.ItemIndex = 0) then
|
2020-06-23 18:16:25 +00:00
|
|
|
begin
|
|
|
|
FF1 := abs(MSF1 / MSErr);
|
|
|
|
FF2 := abs(MSF2 / MSF1F2);
|
2020-11-10 16:46:13 +00:00
|
|
|
FF3 := abs(MSF3 / MSF1F3);
|
2020-06-23 18:16:25 +00:00
|
|
|
FF1F2 := abs(MSF1F2 / MSErr);
|
2020-11-10 16:46:13 +00:00
|
|
|
FF1F3 := abs(MSF1F3 / MSErr);
|
|
|
|
FF2F3 := abs(MSF2F3 / MSF1F2F3);
|
|
|
|
FF1F2F3 := abs(MSF1F2F3 / MSErr);
|
2020-11-09 21:52:26 +00:00
|
|
|
ProbF1 := ProbF(FF1, DFF1, DFErr);
|
|
|
|
ProbF2 := ProbF(FF2, DFF2, DFF1F2);
|
2020-11-10 16:46:13 +00:00
|
|
|
ProbF3 := ProbF(FF3, DFF3, DFF1F3);
|
|
|
|
ProbF1F2 := ProbF(FF1F2, DFF1F2, DFErr);
|
|
|
|
ProbF1F3 := ProbF(FF1F3, DFF1F3, DFErr);
|
|
|
|
ProbF2F3 := ProbF(FF2F3, DFF2F3, DFF1F2F3);
|
|
|
|
ProbF1F2F3 := ProbF(FF1F2F3, DFF1F2F3, DFErr);
|
|
|
|
end;
|
|
|
|
|
|
|
|
// F test if factor b is random and A and C are Fixed
|
|
|
|
if (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 1) and (Fact3Combo.ItemIndex = 0) then
|
2020-06-23 18:16:25 +00:00
|
|
|
begin
|
|
|
|
FF1 := abs(MSF1 / MSF1F2);
|
|
|
|
FF2 := abs(MSF2 / MSErr);
|
2020-11-10 16:46:13 +00:00
|
|
|
FF3 := abs(MSF3 / MSF2F3);
|
2020-06-23 18:16:25 +00:00
|
|
|
FF1F2 := abs(MSF1F2 / MSErr);
|
2020-11-10 16:46:13 +00:00
|
|
|
FF1F3 := abs(MSF1F3 / MSF1F2F3);
|
|
|
|
FF2F3 := abs(MSF2F3 / MSErr);
|
|
|
|
FF1F2F3 := abs(MSF1F2F3 / MSErr);
|
2020-11-09 21:52:26 +00:00
|
|
|
ProbF1 := ProbF(FF1, DFF1, DFF1F2);
|
|
|
|
ProbF2 := ProbF(FF2, DFF2, DFErr);
|
2020-11-10 16:46:13 +00:00
|
|
|
ProbF3 := ProbF(FF3, DFF3, DFF2F3);
|
|
|
|
ProbF1F2 := ProbF(FF1F2, DFF1F2, DFErr);
|
|
|
|
ProbF1F3 := ProbF(FF1F3, DFF1F3, DFF1F2F3);
|
|
|
|
ProbF2F3 := ProbF(FF2F3, DFF2F3, DFErr);
|
|
|
|
ProbF1F2F3 := ProbF(FF1F2F3, DFF1F2F3, DFErr);
|
2020-06-23 18:16:25 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// F test if factor c is random and A and B are Fixed
|
|
|
|
if (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 0) and (Fact3Combo.ItemIndex = 1) then
|
|
|
|
begin
|
|
|
|
FF1 := abs(MSF1 / MSF1F3);
|
|
|
|
FF2 := abs(MSF2 / MSF2F3);
|
|
|
|
FF3 := abs(MSF3 / MSErr);
|
|
|
|
FF1F2 := abs(MSF1F2 / MSF1F2F3);
|
|
|
|
FF1F3 := abs(MSF1F3 / MSErr);
|
|
|
|
FF2F3 := abs(MSF2F3 / MSErr);
|
|
|
|
FF1F2F3 := abs(MSF1F2F3 / MSErr);
|
|
|
|
ProbF1 := ProbF(FF1, DFF1, DFF1F3);
|
|
|
|
ProbF2 := ProbF(FF2, DFF2, DFF2F3);
|
|
|
|
ProbF3 := ProbF(FF3, DFF3, DFErr);
|
|
|
|
ProbF1F2 := ProbF(FF1F2, DFF1F2, DFF1F2F3);
|
|
|
|
ProbF1F3 := ProbF(FF1F3, DFF1F3, DFErr);
|
|
|
|
ProbF2F3 := ProbF(FF2F3, DFF2F3, DFErr);
|
|
|
|
ProbF1F2F3 := ProbF(FF1F2F3, DFF1F2F3, DFErr);
|
|
|
|
end;
|
2020-06-23 18:16:25 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// F tests if A is fixed, B and C are random
|
|
|
|
if (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 1) and (Fact3Combo.ItemIndex = 1) then
|
|
|
|
begin
|
|
|
|
if (MSF1F3 + MSF1F2 - MSF1F2F3) <= 0.0
|
|
|
|
then OKTerms[1] := false
|
|
|
|
else FF1 := abs(MSF1 / (MSF1F3 + MSF1F2 - MSF1F2F3));
|
|
|
|
FF2 := abs(MSF2 / MSF2F3);
|
|
|
|
FF3 := abs(MSF3 / MSF2F3);
|
|
|
|
FF1F2 := abs(MSF1F2 / MSF1F2F3);
|
|
|
|
FF1F3 := abs(MSF1F3 / MSF1F2F3);
|
|
|
|
FF2F3 := abs(MSF2F3 / MSErr);
|
|
|
|
FF1F2F3 := abs(MSF1F2F3 / MSErr);
|
|
|
|
if (DFF1F3 + DFF1F2 - DFF1F2F3) <= 0
|
|
|
|
then OKTerms[8] := false
|
|
|
|
else ProbF1 := ProbF(FF1, DFF1, DFF1F3 + DFF1F2 - DFF1F2F3);
|
|
|
|
ProbF2 := ProbF(FF2, DFF2, DFF2F3);
|
|
|
|
ProbF3 := ProbF(FF3, DFF3, DFF2F3);
|
|
|
|
ProbF1F2 := ProbF(FF1F2, DFF1F2, DFF1F2F3);
|
|
|
|
ProbF1F3 := ProbF(FF1F3, DFF1F3, DFF1F2F3);
|
|
|
|
ProbF2F3 := ProbF(FF2F3, DFF2F3, DFErr);
|
|
|
|
ProbF1F2F3 := ProbF(FF1F2F3, DFF1F2F3, DFErr);
|
|
|
|
end;
|
2020-11-09 15:39:10 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// F tests if B is fixed, A and C are random
|
|
|
|
if (Fact1Combo.ItemIndex = 1) and (Fact2Combo.ItemIndex = 0) and (Fact3Combo.ItemIndex = 1) then
|
|
|
|
begin
|
|
|
|
FF1 := abs(MSF2 / MSF1F3);
|
|
|
|
if (MSF2F3 + MSF1F2 - MSF1F2F3) <= 0.0
|
|
|
|
then OKTerms[2] := false
|
|
|
|
else FF2 := abs(MSF1 / (MSF2F3 + MSF1F2 - MSF1F2F3));
|
|
|
|
FF3 := abs(MSF3 / MSF1F3);
|
|
|
|
FF1F2 := abs(MSF1F2 / MSF1F2F3);
|
|
|
|
FF1F3 := abs(MSF1F3 / MSErr);
|
|
|
|
FF2F3 := abs(MSF2F3 / MSF1F2F3);
|
|
|
|
FF1F2F3 := abs(MSF1F2F3 / MSErr);
|
|
|
|
ProbF1 := probf(FF2,DFF2,DFF1F3);
|
|
|
|
if (DFF2F3 + DFF1F2 - DFF1F2F3) <= 0
|
|
|
|
then OKTerms[9] := false
|
|
|
|
else ProbF2 := ProbF(FF1, DFF1, DFF2F3 + DFF1F2 - DFF1F2F3);
|
|
|
|
ProbF3 := ProbF(FF3, DFF3, DFF1F3);
|
|
|
|
ProbF1F2 := ProbF(FF1F2, DFF1F2, DFF1F2F3);
|
|
|
|
ProbF1F3 := Probf(FF1F3, DFF1F3, DFErr);
|
|
|
|
ProbF2F3 := ProbF(FF2F3, DFF2F3, DFF1F2F3);
|
|
|
|
ProbF1F2F3 := ProbF(FF1F2F3, DFF1F2F3, DFErr);
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// F tests if C is fixed A and B are random
|
|
|
|
if (Fact1Combo.ItemIndex = 1) and (Fact2Combo.ItemIndex = 1) and (Fact3Combo.ItemIndex = 0) then
|
|
|
|
begin
|
|
|
|
FF1 := abs(MSF1 / MSF1F2);
|
|
|
|
FF2 := abs(MSF2 / MSF1F2);
|
|
|
|
if (MSF2F3 + MSF1F3 - MSF1F2F3) <= 0.0
|
|
|
|
then OKTerms[3] := false
|
|
|
|
else FF3 := abs(MSF3 / (MSF2F3 + MSF1F3 - MSF1F2F3));
|
|
|
|
FF1F2 := abs(MSF2F3 / MSErr);
|
|
|
|
FF1F3 := abs(MSF1F2 / MSF1F2F3);
|
|
|
|
FF2F3 := abs(MSF1F3 / MSF1F2F3);
|
|
|
|
FF1F2F3 := abs(MSF1F2F3 / MSErr);
|
|
|
|
ProbF1 := probf(FF3,DFF3,DFF1F2);
|
|
|
|
ProbF2 := probf(FF2,DFF2,DFF1F2);
|
|
|
|
if (DFF2F3 + DFF1F3 - DFF1F2F3) <= 0
|
|
|
|
then OKTerms[10] := false
|
|
|
|
else ProbF3 := ProbF(FF1, DFF1, DFF2F3 + DFF1F3 - DFF1F2F3);
|
|
|
|
ProbF1F2 := ProbF(FF2F3, DFF2F3, DFErr);
|
|
|
|
ProbF1F3 := ProbF(FF1F2, DFF1F2, DFF1F2F3);
|
|
|
|
ProbF2F3 := ProbF(FF1F3, DFF1F3, DFF1F2F3);
|
|
|
|
ProbF1F2F3 := ProbF(FF1F2F3, DFF1F2F3, DFErr);
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if (ProbF1 > 1.0) then ProbF1 := 1.0;
|
|
|
|
if (ProbF2 > 1.0) then ProbF2 := 1.0;
|
|
|
|
if ProbF3 > 1.0 then ProbF3 := 1.0;
|
|
|
|
if (ProbF1F2 > 1.0) then ProbF1F2 := 1.0;
|
|
|
|
if ProbF1F3 > 1.0 then ProbF1F3 := 1.0;
|
|
|
|
if ProbF2F3 > 1.0 then ProbF2F3 := 1.0;
|
|
|
|
if ProbF1F2F3 > 1.0 then ProbF1F2F3 := 1.0;
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Obtain omega squared (proportion of dependent variable explained)
|
|
|
|
if (OmegaF1 < 0.0) then OmegaF1 := 0.0;
|
|
|
|
if (OmegaF2 < 0.0) then OmegaF2 := 0.0;
|
|
|
|
if OmegaF3 < 0.0 then OmegaF3 := 0.0;
|
|
|
|
if (OmegaF1F2 < 0.0) then OmegaF1F2 := 0.0;
|
|
|
|
if OmegaF1F3 < 0.0 then OmegaF1F3 := 0.0;
|
|
|
|
if OmegaF2F3 < 0.0 then OmegaF2F3 := 0.0;
|
|
|
|
if OmegaF1F2F3 < 0.0 then OmegaF1F2F3 := 0.0;
|
|
|
|
if (Omega < 0.0) then Omega := 0.0;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
Result := true;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.Compute;
|
|
|
|
var
|
|
|
|
DepValues, F1Values, F2Values, F3Values: DblDyneVec;
|
|
|
|
begin
|
|
|
|
// Get column numbers of dependent variable and factors
|
|
|
|
Init;
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Get min and max of each factor code
|
|
|
|
// The function fails when codes are not integers or not consecutive.
|
|
|
|
if not GetLevels(DepValues, F1Values, F2Values, F3Values) then
|
|
|
|
exit;
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Do analysis
|
|
|
|
case nofactors of
|
|
|
|
1 : // Single factor anova
|
|
|
|
begin
|
|
|
|
Init1Way;
|
|
|
|
if Calc1Way(DepValues, F1Values) then
|
|
|
|
begin
|
|
|
|
OneWayTable;
|
|
|
|
OneWayPostHoc;
|
|
|
|
OneWayPlot;
|
|
|
|
end;
|
|
|
|
end;
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
2 : // Rwo-way anova
|
|
|
|
begin
|
|
|
|
Init2Way;
|
|
|
|
if Calc2Way(DepValues, F1Values, F2Values) then
|
|
|
|
begin
|
|
|
|
TwoWayTable;
|
|
|
|
TwoWayContrasts;
|
|
|
|
TwoWayPlot;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
3 : // three way anova
|
|
|
|
begin
|
|
|
|
Init3Way;
|
|
|
|
if Calc3Way(DepValues, F1Values, F2Values, F3Values) then
|
|
|
|
begin
|
|
|
|
ThreeWayTable;
|
|
|
|
ThreeWayContrasts;
|
|
|
|
ThreeWayPlot;
|
|
|
|
end;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
|
2020-11-09 21:52:26 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.DepInClick(Sender: TObject);
|
2020-11-09 21:52:26 +00:00
|
|
|
var
|
2020-11-10 16:46:13 +00:00
|
|
|
index: integer;
|
2020-11-09 21:52:26 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
index := VarList.ItemIndex;
|
|
|
|
if (index > -1) and (DepVarEdit.Text = '') then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
DepVarEdit.Text := VarList.Items[index];
|
|
|
|
VarList.Items.Delete(index);
|
|
|
|
UpdateBtnStates;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-11-09 21:52:26 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.DepOutClick(Sender: TObject);
|
2020-11-09 21:52:26 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
if DepVarEdit.Text <> '' then
|
|
|
|
begin
|
|
|
|
VarList.Items.Add(DepVarEdit.Text);
|
|
|
|
DepVarEdit.Text := '';
|
|
|
|
end;
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.Fact1InClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
index: integer;
|
|
|
|
begin
|
|
|
|
index := VarList.ItemIndex;
|
|
|
|
if (index > -1) and (Factor1Edit.Text = '') then
|
|
|
|
begin
|
|
|
|
Factor1Edit.Text := VarList.Items[index];
|
|
|
|
VarList.Items.Delete(index);
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
end;
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
|
|
|
|
procedure TBlksAnovaForm.Fact1OutClick(Sender: TObject);
|
|
|
|
begin
|
|
|
|
if Factor1Edit.Text <> '' then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
VarList.Items.Add(Factor1Edit.Text);
|
|
|
|
Factor1Edit.Text := '';
|
|
|
|
UpdateBtnStates;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.Fact2InClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
index: integer;
|
|
|
|
begin
|
|
|
|
index := VarList.ItemIndex;
|
|
|
|
if (index > -1) and (Factor2Edit.Text = '') then
|
|
|
|
begin
|
|
|
|
Factor2Edit.Text := VarList.Items[index];
|
|
|
|
VarList.Items.Delete(index);
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
2020-11-09 21:52:26 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.Fact2OutClick(Sender: TObject);
|
2020-11-09 21:52:26 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
if Factor2Edit.Text <> '' then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
VarList.Items.Add(Factor2Edit.Text);
|
|
|
|
Factor2Edit.Text := '';
|
|
|
|
UpdateBtnStates;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
|
|
|
|
procedure TBlksAnovaForm.Fact3InClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
index: integer;
|
|
|
|
begin
|
|
|
|
index := VarList.ItemIndex;
|
|
|
|
if (index > -1) and (Factor3Edit.Text = '') then
|
2020-11-09 21:52:26 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
Factor3Edit.Text := VarList.Items[index];
|
|
|
|
VarList.Items.Delete(index);
|
|
|
|
UpdateBtnStates;
|
2020-11-09 21:52:26 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
|
|
|
|
procedure TBlksAnovaForm.Fact3OutClick(Sender: TObject);
|
|
|
|
begin
|
|
|
|
if Factor3Edit.Text <> '' then
|
|
|
|
begin
|
|
|
|
VarList.Items.Add(Factor3Edit.Text);
|
|
|
|
Factor3Edit.Text := '';
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
|
|
|
|
{ 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 TBlksAnovaForm.GetDataIndices(out ix, iy, iz: Integer);
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-11-10 16:46:13 +00:00
|
|
|
index, i1, i2, i3: Integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
index := FChartComboBox.ItemIndex;
|
|
|
|
i1 := 3;
|
|
|
|
i2 := i1 + NF3Cells;
|
|
|
|
i3 := i2 + NF3Cells;
|
|
|
|
if (index >= i1) and (index < i3) then
|
|
|
|
begin
|
|
|
|
if index < i2 then
|
|
|
|
begin
|
|
|
|
ix := 1;
|
|
|
|
iy := 2;
|
|
|
|
iz := index - i1;
|
|
|
|
end else
|
|
|
|
begin
|
|
|
|
ix := 2;
|
|
|
|
iy := 1;
|
|
|
|
iz := index - i2;
|
|
|
|
end;
|
2020-06-23 17:16:32 +00:00
|
|
|
exit;
|
2020-11-10 16:46:13 +00:00
|
|
|
end;
|
2020-06-23 17:16:32 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
i1 := i3;
|
|
|
|
i2 := i1 + NF2Cells;
|
|
|
|
i3 := i2 + NF2Cells;
|
|
|
|
if (index >= i1) and (index < i3) then
|
|
|
|
begin
|
|
|
|
if index < i2 then
|
|
|
|
begin
|
|
|
|
ix := 1;
|
|
|
|
iy := 3;
|
|
|
|
iz := index - i1;
|
|
|
|
end else
|
|
|
|
begin
|
|
|
|
ix := 3;
|
|
|
|
iy := 1;
|
|
|
|
iz := index - i2;
|
|
|
|
end;
|
2020-06-23 17:16:32 +00:00
|
|
|
exit;
|
2020-11-10 16:46:13 +00:00
|
|
|
end;
|
2020-06-23 17:16:32 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
i1 := i3;
|
|
|
|
i2 := i1 + NF1Cells;
|
|
|
|
i3 := i2 + NF1Cells;
|
|
|
|
if (index >= i1) and (index < i3) then
|
2020-06-23 17:16:32 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
if index < i2 then
|
|
|
|
begin
|
|
|
|
ix := 2;
|
|
|
|
iy := 3;
|
|
|
|
iz := index - i1;
|
|
|
|
end else
|
2020-06-23 17:16:32 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
ix := 3;
|
|
|
|
iy := 2;
|
|
|
|
iz := index - i2;
|
2020-06-23 17:16:32 +00:00
|
|
|
end;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
function TBlksAnovaForm.GetLevels(
|
|
|
|
out DepValues, F1Values, F2Values, F3Values: DblDyneVec): Boolean;
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-11-10 16:46:13 +00:00
|
|
|
mx, mn: Double;
|
2020-11-13 13:16:59 +00:00
|
|
|
msg: String;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
Result := false;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
DepValues := nil;
|
|
|
|
F1Values := nil;
|
|
|
|
F2Values := nil;
|
|
|
|
F3Values := nil;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Extract dependent variable values
|
|
|
|
DepValues := CollectVecValues(OS3MainFrm.DataGrid, ColNoSelected[0], ColNoSelected);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Extract factor 1 values
|
|
|
|
F1Values := CollectVecValues(OS3MainFrm.DataGrid, ColNoSelected[1], ColNoSelected);
|
|
|
|
VecMaxMin(F1Values, mx, mn);
|
|
|
|
MaxF1 := round(mx);
|
|
|
|
MinF1 := round(mn);
|
|
|
|
NF1Cells := MaxF1 - MinF1 + 1;
|
2020-11-13 13:16:59 +00:00
|
|
|
if not CheckFactorCodes(Factor1Edit.Text, F1Values, msg) then
|
|
|
|
begin
|
|
|
|
ErrorMsg(msg);
|
2020-11-10 16:46:13 +00:00
|
|
|
exit;
|
2020-11-13 13:16:59 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Extract factor 2 values when available
|
|
|
|
if NoFactors >= 2 then
|
|
|
|
begin
|
|
|
|
F2Values := CollectVecValues(OS3MainFrm.DataGrid, ColNoSelected[2], ColNoSelected);
|
|
|
|
VecMaxMin(F2Values, mx, mn);
|
|
|
|
MaxF2 := round(mx);
|
|
|
|
MinF2 := round(mn);
|
|
|
|
NF2Cells := MaxF2 - MinF2 + 1;
|
2020-11-13 13:16:59 +00:00
|
|
|
if not CheckFactorCodes(Factor2Edit.Text, F2Values, msg) then
|
|
|
|
begin
|
|
|
|
ErrorMsg(msg);
|
2020-11-10 16:46:13 +00:00
|
|
|
exit;
|
2020-11-13 13:16:59 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
end else
|
|
|
|
NF2Cells := 0;
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Extract factor 3 values when available
|
|
|
|
if NoFactors = 3 then
|
2020-06-23 17:41:18 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
F3Values := CollectVecValues(OS3MainFrm.DataGrid, ColNoSelected[3], ColNoSelected);
|
|
|
|
VecMaxMin(F3Values, mx, mn);
|
|
|
|
MaxF3 := round(mx);
|
|
|
|
MinF3 := round(mn);
|
|
|
|
NF3Cells := MaxF3 - MinF3 + 1;
|
2020-11-13 13:16:59 +00:00
|
|
|
if not CheckFactorCodes(Factor3Edit.Text, F3Values, msg) then
|
|
|
|
begin
|
|
|
|
ErrorMsg(msg);
|
2020-11-10 16:46:13 +00:00
|
|
|
exit;
|
2020-11-13 13:16:59 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
end else
|
|
|
|
NF3cells := 0;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
Result := true;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.Init;
|
|
|
|
begin
|
|
|
|
if Factor2Edit.Text = '' then
|
|
|
|
NoFactors := 1
|
|
|
|
else if Factor3Edit.Text = '' then
|
|
|
|
NoFactors := 2
|
|
|
|
else
|
|
|
|
NoFactors := 3;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Get column numbers of dependent variable and factors
|
|
|
|
SetLength(ColNoSelected, NoFactors + 1); // because DepVar is at index 0
|
|
|
|
ColNoSelected[0] := GetVariableIndex(OS3MainFrm.DataGrid, DepVarEdit.Text);
|
|
|
|
ColNoSelected[1] := GetVariableIndex(OS3MainFrm.DataGrid, Factor1Edit.Text);
|
|
|
|
if Factor2Edit.Text <> '' then
|
|
|
|
ColNoSelected[2] := GetVariableIndex(OS3MainFrm.DataGrid, Factor2Edit.Text)
|
|
|
|
else
|
|
|
|
ColNoSelected[2] := -1;
|
|
|
|
if Factor3Edit.Text <> '' then
|
|
|
|
ColNoSelected[3] := GetVariableIndex(OS3MainFrm.DataGrid, Factor3Edit.Text)
|
|
|
|
else
|
|
|
|
ColNoSelected[3] := -1;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
CorrectionsGroup.Enabled := (NoFactors = 1);
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.Init1Way;
|
|
|
|
begin
|
|
|
|
cellCnts := nil;
|
|
|
|
cellSums := nil;
|
|
|
|
cellVars := nil;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
SetLength(cellCnts, NF1Cells);
|
|
|
|
SetLength(cellSums, NF1Cells);
|
|
|
|
SetLength(cellVars, NF1Cells);
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.Init2Way;
|
|
|
|
begin
|
|
|
|
Init1Way;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
RowSums := nil;
|
|
|
|
ColSums := nil;
|
|
|
|
RowCount := nil;
|
|
|
|
ColCount := nil;
|
|
|
|
Counts := nil;
|
|
|
|
Sums := nil;
|
|
|
|
Vars := nil;
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
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;
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.Init3Way;
|
|
|
|
begin
|
|
|
|
Init2Way;
|
2020-06-23 17:41:18 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
SlcSums := nil;
|
|
|
|
SlcCount := nil;
|
|
|
|
WSum := nil;
|
|
|
|
WX2 := nil;
|
|
|
|
NCnt := nil;
|
2020-06-23 17:41:18 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TBlksAnovaForm.OneWayTable;
|
|
|
|
var
|
|
|
|
lReport: TStrings;
|
|
|
|
i, grpsize: integer;
|
|
|
|
minvar, maxvar, sumvar, sumfreqlogvar, sumDFrecip: double;
|
|
|
|
c, bartlett, cochran, hartley, chiprob: double;
|
|
|
|
maxSize: Integer;
|
|
|
|
begin
|
|
|
|
lReport := TStringList.Create;
|
|
|
|
try
|
|
|
|
lReport.Add('ONE WAY ANALYSIS OF VARIANCE RESULTS');
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('Dependent variable is: %s', [DepVarEdit.Text]);
|
|
|
|
lReport.Add('Independent variable is: %s', [Factor1Edit.Text]);
|
|
|
|
lReport.Add('');
|
|
|
|
|
|
|
|
lReport.Add('-----------------------------------------------------------------------------');
|
|
|
|
lReport.Add('SOURCE D.F. SS MS F PROB.> F Omega Sqr.');
|
|
|
|
lReport.Add('------------- ---- ---------- ---------- ---------- -------- ----------');
|
|
|
|
lReport.Add('Between %4.0f %10.3f %10.3f %10.3f %8.3f %8.3f', [DFF1, SSF1, MSF1, FF1, ProbF1, OmegaF1]);
|
|
|
|
lReport.Add('Within %4.0f %10.3f %10.3f', [DFErr, SSErr, MSErr]);
|
|
|
|
lReport.Add('Total %4.0f %10.3f', [DFTot, SSDep]);
|
|
|
|
lReport.Add('-----------------------------------------------------------------------------');
|
|
|
|
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('MEANS AND VARIABILITY OF THE DEPENDENT VARIABLE');
|
|
|
|
lReport.Add('FOR LEVELS OF THE INDEPENDENT VARIABLE');
|
|
|
|
lReport.Add('---------------------------------------------------');
|
|
|
|
lReport.Add('GROUP MEAN VARIANCE STD.DEV. N');
|
|
|
|
lReport.Add('----- --------- ---------- ---------- ---------');
|
|
|
|
// xxxx xxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxx
|
|
|
|
|
|
|
|
equal_grp := true;
|
|
|
|
minVar := 1e308;
|
|
|
|
maxVar := -minVar;
|
|
|
|
sumVar := 0.0;
|
|
|
|
sumDFRecip := 0.0;
|
|
|
|
sumFreqLogVar := 0.0;
|
|
|
|
|
|
|
|
grpSize := round(cellCnts[0]);
|
|
|
|
MinSize := grpSize; // initialized minimum group size
|
|
|
|
maxSize := grpSize; // initialize maximum group size
|
|
|
|
for i := 0 to NF1Cells-1 do
|
|
|
|
begin
|
|
|
|
grpSize := round(cellCnts[i]);
|
|
|
|
if grpSize < MinSize then
|
|
|
|
begin
|
|
|
|
MinSize := grpSize;
|
|
|
|
equal_grp := false;
|
|
|
|
end;
|
|
|
|
if grpSize > maxSize then
|
|
|
|
maxSize := grpSize;
|
|
|
|
|
|
|
|
if cellCnts[i] > 1 then
|
|
|
|
begin
|
|
|
|
cellVars[i] := (cellVars[i] - sqr(cellSums[i]) / cellCnts[i]) / (cellCnts[i] - 1);
|
|
|
|
if cellvars[i] > maxVar then maxVar := cellVars[i];
|
|
|
|
if cellvars[i] < minVar then minVar := cellVars[i];
|
|
|
|
sumVar :=sumVar + cellVars[i];
|
|
|
|
sumDFRecip := sumDFRecip + 1.0 / (cellCnts[i] - 1);
|
|
|
|
sumFreqLogVar := sumFreqLogVar + (cellCnts[i] - 1) * ln(cellVars[i]); // wp: was log10, but all the other s ahve ln() here
|
|
|
|
end;
|
|
|
|
|
|
|
|
if cellCnts[i] > 0 then
|
|
|
|
lReport.Add('%5d %9.2f %10.2f %10.2f %7d', [
|
|
|
|
i+1, cellSums[i] / cellCnts[i], cellVars[i], sqrt(cellVars[i]), cellCnts[i]
|
|
|
|
]);
|
|
|
|
end;
|
|
|
|
|
|
|
|
lReport.Add('---------------------------------------------------');
|
|
|
|
lReport.Add('TOTAL %9.2f %10.2f %10.2f %7d', [MeanDep, MSDep, sqrt(MSDep), N]);
|
|
|
|
lReport.Add('---------------------------------------------------');
|
|
|
|
lReport.Add('');
|
|
|
|
|
|
|
|
c := 1.0 + (1.0 / (3 * DFF1)) * (sumDFRecip - (1.0 / DFErr));
|
|
|
|
bartlett := (2.303 / c) * (DFErr * ln(MSErr) - sumFreqLogVar); // wp: was log10(),but all the others use ln() here
|
|
|
|
chiProb := 1.0 - ChiSquaredProb(bartlett, round(DFF1));
|
|
|
|
cochran := maxVar / sumVar;
|
|
|
|
hartley := maxVar / minVar;
|
|
|
|
|
|
|
|
lReport.Add(DIVIDER_AUTO);
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('TESTS FOR HOMOGENEITY OF VARIANCE');
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('Hartley Fmax test statistic: %8.3f (%d and %d degrees of freedom)', [hartley, NF1cells, maxSize-1]);
|
|
|
|
lReport.Add('Cochran C statistic: %8.3f (%d and %d degrees of freedom)', [cochran, Nf1cells, maxSize-1]);
|
|
|
|
lReport.Add('Bartlett Chi-square: %8.3f (%.0f degrees of freedom)', [bartlett, DFF1]);
|
|
|
|
lReport.Add(' probability > Chi-Square: %8.3f', [chiprob]);
|
|
|
|
|
|
|
|
FReportFrame.DisplayReport(lReport);
|
|
|
|
finally
|
|
|
|
lReport.Free;
|
2020-06-23 17:41:18 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
end;
|
2020-06-23 17:41:18 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
|
|
|
|
procedure TBlksAnovaForm.OneWayPostHoc;
|
|
|
|
var
|
|
|
|
lReport: TStrings;
|
|
|
|
allAlpha, posthocAlpha: Double;
|
|
|
|
begin
|
|
|
|
if not (ScheffeChk.Checked or TukeyHSDChk.Checked or TukeyBChk.Checked or
|
|
|
|
TukeyKramerChk.Checked or NewmanKeulsChk.Checked or
|
|
|
|
BonferroniChk.Checked or OrthoContrastsChk.Checked) then
|
2020-06-23 17:41:18 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
PostHocPage.TabVisible := false;
|
|
|
|
exit;
|
2020-06-23 17:41:18 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
allAlpha := StrToFloat(OverallAlphaEdit.Text);
|
|
|
|
posthocAlpha := StrToFloat(PostAlphaEdit.Text);
|
|
|
|
|
|
|
|
lReport := TStringList.Create;
|
|
|
|
try
|
|
|
|
if ScheffeChk.Checked then
|
|
|
|
ScheffeTest(MSErr, cellSums, cellCnts, minF1, maxF1, N, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if TukeyHSDChk.Checked and equal_grp then
|
|
|
|
Tukey(MSErr, DFErr, MinSize, cellSums, cellCnts, minF1, maxF1, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if TukeyBChk.Checked and equal_grp then
|
|
|
|
TukeyBTest(MSErr, DFErr, cellSums, cellCnts, minF1, maxF1, MinSize, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if TukeyKramerChk.Checked then
|
|
|
|
Tukey_Kramer(MSErr, DFErr, MinSize, cellSums, cellCnts, minF1, maxF1, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if NewmanKeulsChk.Checked and equal_grp then
|
|
|
|
Newman_Keuls(MSErr, DFErr, MinSize, cellSums, cellCnts, minF1, maxF1, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if BonferroniChk.Checked then
|
|
|
|
Bonferroni(cellSums, cellCnts, cellVars, minF1, maxF1, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if OrthoContrastsChk.Checked then
|
|
|
|
Contrasts(MSErr, DFErr, cellSums, cellCnts, minF1, maxF1, allAlpha, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if BrownForsythe.Checked then
|
|
|
|
BrownForsytheOneWay(lReport);
|
|
|
|
|
|
|
|
if Welch.Checked then
|
|
|
|
WelchOneWay(lReport);
|
|
|
|
|
|
|
|
FPostHocReportFrame.DisplayReport(lReport);
|
|
|
|
|
|
|
|
PosthocPage.TabVisible := true;
|
|
|
|
|
|
|
|
finally
|
|
|
|
lReport.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TBlksAnovaForm.OneWayPlot;
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
if not ShowPlotsChk.Checked then
|
2020-06-23 17:41:18 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
ChartPage.TabVisible := false;
|
|
|
|
exit;
|
2020-06-23 17:41:18 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
FChartFrame.Clear;
|
|
|
|
FChartFrame.SetYTitle('Mean');
|
|
|
|
FSeries := FChartFrame.PlotXY(ptBars, nil, nil, nil, nil, '', DATA_COLORS[0]);
|
|
|
|
with TBarSeries(FSeries) do
|
2020-06-23 17:41:18 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
Styles := nil;
|
|
|
|
Stacked := false;
|
|
|
|
{$IF LCL_FullVersion >= 2010000}
|
|
|
|
DepthBrightnessDelta := -30;
|
|
|
|
{$ENDIF}
|
2020-06-23 17:41:18 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
if Plot3DChk.Checked then
|
|
|
|
FSeries.Depth := 20;
|
2020-06-23 17:41:18 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
FSeries.ListSource.YCount := 1;
|
|
|
|
for i := 0 to NF1Cells-1 do
|
|
|
|
FSeries.AddXY(minF1 + i, cellSums[i] / cellCnts[i], IntToStr(MinF1 + i));
|
|
|
|
FChartFrame.SetXTitle(Factor1Edit.Text + ' codes (Factor A level)');
|
|
|
|
|
|
|
|
FChartCombobox.Parent.Hide;
|
|
|
|
FChartFrame.Chart.Legend.Visible := false;
|
|
|
|
FChartFrame.Chart.BottomAxis.Marks.Source := FSeries.Source;
|
|
|
|
FChartFrame.Chart.BottomAxis.Marks.Style := smsXValue;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TBlksAnovaForm.Plot3dChkChange(Sender: TObject);
|
|
|
|
begin
|
|
|
|
if FSeries is TBarSeries then
|
2020-06-23 17:41:18 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
if Plot3dChk.Checked then
|
|
|
|
TBarSeries(FSeries).Depth := 20
|
|
|
|
else
|
|
|
|
TBarSeries(FSeries).Depth := 0;
|
2020-06-23 17:41:18 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
end;
|
2020-06-23 17:41:18 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
|
|
|
|
procedure TBlksAnovaForm.PopulateChartCombobox(ThreeWay: Boolean);
|
|
|
|
var
|
|
|
|
a, b, c: String;
|
|
|
|
i, idx: Integer;
|
|
|
|
begin
|
|
|
|
a := Factor1Edit.Text;
|
|
|
|
b := Factor2Edit.Text;
|
|
|
|
c := Factor3Edit.Text;
|
|
|
|
|
|
|
|
idx := FChartCombobox.ItemIndex;
|
|
|
|
|
|
|
|
FChartCombobox.Items.Clear;
|
|
|
|
FChartCombobox.Items.Add(a);
|
|
|
|
FChartCombobox.Items.Add(b);
|
|
|
|
if ThreeWay then
|
|
|
|
FChartCombobox.Items.Add(c);
|
|
|
|
|
|
|
|
{
|
|
|
|
if InteractChk.Checked then
|
2020-06-23 17:41:18 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
FChartComboBox.ItemIndex := EnsureRange(idx, 0, FChartComboBox.Items.Count-1);
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TBlksAnovaForm.Reset;
|
|
|
|
var
|
|
|
|
i: integer;
|
|
|
|
begin
|
|
|
|
inherited;
|
|
|
|
|
2020-11-12 18:31:56 +00:00
|
|
|
if FPostHocReportFrame <> nil then
|
|
|
|
FPostHocReportFrame.Clear;
|
|
|
|
if FChartCombobox <> nil then
|
|
|
|
FChartCombobox.Items.Clear;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
VarList.Clear;
|
|
|
|
for i := 1 to NoVariables do
|
|
|
|
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
|
|
|
|
|
|
|
|
DepVarEdit.Clear;
|
|
|
|
Factor1Edit.Clear;
|
|
|
|
Factor2Edit.Clear;
|
|
|
|
Factor3Edit.Clear;
|
|
|
|
Fact1Combo.ItemIndex := 0;
|
|
|
|
Fact2Combo.ItemIndex := 0;
|
|
|
|
Fact3Combo.ItemIndex := 0;
|
|
|
|
ScheffeChk.Checked := false;
|
|
|
|
TukeyHSDChk.Checked := false;
|
|
|
|
TukeyBChk.Checked := false;
|
|
|
|
TukeyKramerChk.Checked := false;
|
|
|
|
NewmanKeulsChk.Checked := false;
|
|
|
|
BonferroniChk.Checked := false;
|
|
|
|
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
{ OnChange event handler for the ChartCombobox. Displays the chart associated
|
|
|
|
with the current ItemIndex. }
|
|
|
|
procedure TBlksAnovaForm.SelectThreeWayPlot(Sender: TObject);
|
|
|
|
var
|
|
|
|
i, j, k, idx, ix, iy, iz: Integer;
|
|
|
|
item: PChartDataItem;
|
|
|
|
begin
|
|
|
|
FStyles.Styles.Clear;
|
|
|
|
FSeries.Clear;
|
|
|
|
|
|
|
|
case FChartComboBox.ItemIndex of
|
|
|
|
0: begin // Plot means vs factor A
|
|
|
|
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 + ' 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 + ' 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 + ' codes');
|
|
|
|
FChartFrame.SetTitle(Factor3Edit.Text);
|
|
|
|
end;
|
|
|
|
else
|
|
|
|
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 (ix = 2) and (iy = 1) then
|
|
|
|
begin
|
|
|
|
FSeries.ListSource.YCount := NF1Cells;
|
|
|
|
for j := 0 to NF2Cells-1 do
|
|
|
|
begin
|
|
|
|
idx := FSeries.AddXY(minF2 + j, NaN, IntToStr(minF2 + j));
|
|
|
|
item := FSeries.Source.Item[idx];
|
|
|
|
for i := 0 to NF1Cells-1 do
|
|
|
|
item^.SetY(i, 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(Factor2Edit.Text + ' codes');
|
|
|
|
for i := 0 to NF1Cells-1 do
|
|
|
|
with TChartStyle(FStyles.styles.Add) do
|
|
|
|
begin
|
|
|
|
Brush.Color := DATA_COLORS[i mod Length(DATA_COLORS)];
|
|
|
|
UseBrush := True;
|
|
|
|
Text := Format('%s = %s', [Factor1Edit.Text, IntToStr(MinF1 + i)]);
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if (ix = 1) and (iy = 3) then
|
|
|
|
begin
|
|
|
|
FSeries.ListSource.YCount := NF3Cells;
|
|
|
|
for i := 0 to NF1Cells-1 do
|
|
|
|
begin
|
|
|
|
idx := FSeries.AddXY(minF1 + i, NaN, IntToStr(minF1 + i));
|
|
|
|
item := FSeries.Source.Item[idx];
|
|
|
|
for k := 0 to NF3Cells-1 do
|
|
|
|
item^.SetY(k, wsum[i, iz, k] / ncnt[i, iz, k]);
|
|
|
|
end;
|
|
|
|
FChartFrame.SetTitle(Format('Factor "%s" x Factor "%s"' + LineEnding + '"%s" = %d', [
|
|
|
|
Factor1Edit.Text, Factor3Edit.Text, Factor2Edit.Text, MinF2 + iz]));
|
|
|
|
FChartFrame.SetXTitle(Factor1Edit.Text + ' codes');
|
|
|
|
for k := 0 to NF3Cells-1 do
|
|
|
|
with TChartStyle(FStyles.styles.Add) do
|
|
|
|
begin
|
|
|
|
Brush.Color := DATA_COLORS[k mod Length(DATA_COLORS)];
|
|
|
|
UseBrush := True;
|
|
|
|
Text := Format('%s = %s', [Factor3Edit.Text, IntToStr(MinF3 + k)]);
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if (ix = 3) and (iy = 1) then
|
|
|
|
begin
|
|
|
|
FSeries.ListSource.YCount := NF1Cells;
|
|
|
|
for k := 0 to NF3Cells-1 do
|
|
|
|
begin
|
|
|
|
idx := FSeries.AddXY(minF3 + k, NaN, IntToStr(minF3 + k));
|
|
|
|
item := FSeries.Source.Item[idx];
|
|
|
|
for i := 0 to NF1Cells-1 do
|
|
|
|
item^.SetY(i, wsum[i, iz, k] / ncnt[i, iz, k]);
|
|
|
|
end;
|
|
|
|
FChartFrame.SetTitle(Format('Factor "%s" x Factor "%s"' + LineEnding + '"%s" = %d', [
|
|
|
|
Factor1Edit.Text, Factor3Edit.Text, Factor2Edit.Text, MinF2 + iz]));
|
|
|
|
FChartFrame.SetXTitle(Factor3Edit.Text + ' codes');
|
|
|
|
for i := 0 to NF1Cells-1 do
|
|
|
|
with TChartStyle(FStyles.styles.Add) do
|
|
|
|
begin
|
|
|
|
Brush.Color := DATA_COLORS[i mod Length(DATA_COLORS)];
|
|
|
|
UseBrush := True;
|
|
|
|
Text := Format('%s = %s', [Factor1Edit.Text, IntToStr(MinF1 + i)]);
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if (ix = 2) and (iy = 3) then
|
|
|
|
begin
|
|
|
|
FSeries.ListSource.YCount := NF3Cells;
|
|
|
|
for j := 0 to NF2Cells-1 do
|
|
|
|
begin
|
|
|
|
idx := FSeries.AddXY(minF2 + j, NaN, IntToStr(minF2 + j));
|
|
|
|
item := FSeries.Source.Item[idx];
|
|
|
|
for k := 0 to NF3Cells-1 do
|
|
|
|
item^.SetY(k, wsum[iz, j, k] / ncnt[iz, j, k]);
|
|
|
|
end;
|
|
|
|
FChartFrame.SetTitle(Format('Factor "%s" x Factor "%s"' + LineEnding + '"%s" = %d', [
|
|
|
|
Factor2Edit.Text, Factor3Edit.Text, Factor1Edit.Text, MinF1 + iz]));
|
|
|
|
FChartFrame.SetXTitle(Factor2Edit.Text + ' codes');
|
|
|
|
for k := 0 to NF3Cells-1 do
|
|
|
|
with TChartStyle(FStyles.styles.Add) do
|
|
|
|
begin
|
|
|
|
Brush.Color := DATA_COLORS[k mod Length(DATA_COLORS)];
|
|
|
|
UseBrush := True;
|
|
|
|
Text := Format('%s = %s', [Factor3Edit.Text, IntToStr(MinF3 + k)]);
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if (ix = 3) and (iy = 2) then
|
|
|
|
begin
|
|
|
|
FSeries.ListSource.YCount := NF2Cells;
|
|
|
|
for k := 0 to NF3Cells-1 do
|
|
|
|
begin
|
|
|
|
idx := FSeries.AddXY(minF3 + k, NaN, IntToStr(minF3 + k));
|
|
|
|
item := FSeries.Source.Item[idx];
|
|
|
|
for j := 0 to NF2Cells-1 do
|
|
|
|
item^.SetY(j, wsum[iz, j, k] / ncnt[iz, j, k]);
|
|
|
|
end;
|
|
|
|
FChartFrame.SetTitle(Format('Factor "%s" x Factor "%s"' + LineEnding + '"%s" = %d', [
|
|
|
|
Factor2Edit.Text, Factor3Edit.Text, Factor1Edit.Text, MinF1 + iz]));
|
|
|
|
FChartFrame.SetXTitle(Factor3Edit.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
|
|
|
|
raise Exception.Create('Fatal error in SelectThreeWayPlot');
|
2020-06-23 17:41:18 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if (FSeries is TBarSeries) then
|
2020-06-23 17:41:18 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
if FStyles.Styles.Count > 0 then
|
|
|
|
begin
|
|
|
|
TBarSeries(FSeries).Styles := FStyles;
|
|
|
|
FSeries.Legend.Multiplicity := lmStyle;
|
|
|
|
end else
|
|
|
|
FSeries.Legend.Multiplicity := lmSingle;
|
2020-06-23 17:41:18 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
FChartFrame.Chart.BottomAxis.Marks.Source := FSeries.Source;
|
|
|
|
FChartFrame.Chart.BottomAxis.Marks.Style := smsLabel;
|
|
|
|
FChartFrame.Chart.Legend.Visible := FSeries.Source.YCount > 1;
|
2020-11-09 15:39:10 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
FChartFrame.UpdateBtnStates;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.SelectTwoWayPlot(Sender: TObject);
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-11-10 16:46:13 +00:00
|
|
|
i, j, idx: Integer;
|
|
|
|
item: PChartDataItem;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
FStyles.Styles.Clear;
|
|
|
|
FSeries.Clear;
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
case FChartCombobox.ItemIndex of
|
|
|
|
0: begin // Plot means vs factor A
|
|
|
|
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 + ' 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 + ' codes');
|
|
|
|
FChartFrame.SetTitle(Factor2Edit.Text);
|
|
|
|
end;
|
|
|
|
2: begin // Plot interaction A*B vs A
|
|
|
|
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, sums[i, j] / counts[i, j]);
|
|
|
|
end;
|
|
|
|
FChartFrame.SetTitle(Format('Factor "%s" x Factor "%s"', [Factor1Edit.Text, Factor2Edit.Text]));
|
|
|
|
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;
|
|
|
|
3: begin // Plot means vs interaction A*B vs B
|
|
|
|
FSeries.ListSource.YCount := NF1Cells;
|
|
|
|
for j := 0 to NF2Cells-1 do
|
|
|
|
begin
|
|
|
|
idx := FSeries.AddXY(minF2 + j, NaN, IntToStr(minF2 + j));
|
|
|
|
item := FSeries.Source.Item[idx];
|
|
|
|
for i := 0 to NF1Cells-1 do
|
|
|
|
item^.SetY(i, sums[i, j] / counts[i, j]);
|
|
|
|
end;
|
|
|
|
FChartFrame.SetTitle(Format('Factor "%s" x Factor "5s"', [Factor1Edit.Text, Factor2Edit.Text]));
|
|
|
|
FChartFrame.SetXTitle(Factor2Edit.Text + ' codes');
|
|
|
|
for i := 0 to NF1Cells-1 do
|
|
|
|
with TChartStyle(FStyles.styles.Add) do
|
|
|
|
begin
|
|
|
|
Brush.Color := DATA_COLORS[i mod Length(DATA_COLORS)];
|
|
|
|
UseBrush := True;
|
|
|
|
Text := Format('%s %s', [Factor1Edit.Text, IntToStr(MinF1 + i)]);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end; // case
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if (FSeries is TBarSeries) then
|
|
|
|
begin
|
|
|
|
if FStyles.Styles.Count > 0 then
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
TBarSeries(FSeries).Styles := FStyles;
|
|
|
|
FSeries.Legend.Multiplicity := lmStyle;
|
2020-11-10 15:11:42 +00:00
|
|
|
end else
|
2020-11-10 16:46:13 +00:00
|
|
|
FSeries.Legend.Multiplicity := lmSingle;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
FChartFrame.Chart.BottomAxis.Marks.Source := FSeries.Source;
|
|
|
|
FChartFrame.Chart.BottomAxis.Marks.Style := smsLabel;
|
|
|
|
FChartFrame.Chart.Legend.Visible := FSeries.Source.YCount > 1;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
FChartFrame.UpdateBtnStates;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.ShowPlotsChkChange(Sender: TObject);
|
|
|
|
begin
|
|
|
|
ChartPage.TabVisible := ShowPlotsChk.Checked;
|
|
|
|
Plot3DChk.Enabled := ShowPlotsChk.Checked;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TBlksAnovaForm.ThreeWayContrasts;
|
|
|
|
var
|
|
|
|
lReport: TStrings;
|
|
|
|
i, j, k: integer;
|
|
|
|
value: double;
|
|
|
|
variances: DblDyneVec = nil;
|
|
|
|
RowSS, ColSS, SlcSS: double;
|
|
|
|
totalCells: Integer;
|
|
|
|
allAlpha, posthocAlpha: Double;
|
|
|
|
begin
|
|
|
|
if not (ScheffeChk.Checked or TukeyHSDChk.Checked or TukeyBChk.Checked or
|
|
|
|
TukeyKramerChk.Checked or NewmanKeulsChk.Checked or
|
|
|
|
BonferroniChk.Checked or OrthoContrastsChk.Checked) then
|
|
|
|
begin
|
|
|
|
PostHocPage.TabVisible := false;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
allAlpha := StrToFloat(OverallAlphaEdit.Text);
|
|
|
|
PostHocAlpha := StrToFloat(PostAlphaEdit.Text);
|
|
|
|
|
|
|
|
totalCells := NF1Cells + NF2Cells + NF3Cells;
|
|
|
|
SetLength(variances, totalCells);
|
|
|
|
|
|
|
|
lReport := TStringList.Create;
|
|
|
|
try
|
|
|
|
// Do row comparisons
|
|
|
|
if (NF1Cells > 2) and (ProbF1 < allAlpha) then
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
for i := 0 to NoGrpsA-1 do
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
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]) / (RowCount[i] - 1);
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport.Add('COMPARISONS AMONG ROWS');
|
|
|
|
|
|
|
|
// get smallest group size
|
|
|
|
value := 1e20;
|
|
|
|
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 NewmanKeulsChk.Checked and equal_grp then
|
|
|
|
Newman_Keuls(MSErr, DFErr, value, RowSums, RowCount, MinF1, MaxF1, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if BonferroniChk.Checked then
|
|
|
|
Bonferroni(RowSums, RowCount, variances, MinF1, MaxF1, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if OrthoContrastsChk.Checked then
|
|
|
|
Contrasts(MSErr, DFErr, RowSums, RowCount, MinF1, MaxF1, allAlpha, postHocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Do column comparisons
|
|
|
|
if (NF2Cells > 2) and (ProbF2 < allAlpha) then
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
|
|
|
for j := 0 to NoGrpsB-1 do
|
2020-11-10 16:46:13 +00:00
|
|
|
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]) / (ColCount[j] - 1);
|
|
|
|
end;
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
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];
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if ScheffeChk.Checked then
|
|
|
|
ScheffeTest(MSErr, ColSums, ColCount, MinF2, MaxF2, N, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if TukeyHSDChk.Checked and equal_grp then
|
|
|
|
Tukey(MSErr, DFErr, value, ColSums, ColCount, MinF2, MaxF2, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if TukeyBChk.Checked and equal_grp then
|
|
|
|
TukeyBTest(MSErr, DFErr, ColSums, ColCount, MinF2, MaxF2, value, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if TukeyKramerChk.Checked and equal_grp then
|
|
|
|
Tukey_Kramer(MSErr, DFErr, value, ColSums, ColCount, MinF2, MaxF2, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if NewmanKeulsChk.Checked and equal_grp then
|
|
|
|
Newman_Keuls(MSErr, DFErr, value, ColSums, ColCount, MinF2, MaxF2, posthocAlpha, lReport);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if BonferroniChk.Checked then
|
|
|
|
Bonferroni(ColSums, ColCount, variances, MinF2, MaxF2, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if OrthoContrastsChk.Checked then
|
|
|
|
Contrasts(MSErr, DFErr, ColSums, ColCount, MinF2, MaxF2, allAlpha, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Do slice comparisons
|
|
|
|
if (NF3Cells > 2) and (ProbF3 < allAlpha) then
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
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]) / (SlcCount[k] - 1);
|
|
|
|
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];
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if ScheffeChk.Checked then
|
|
|
|
ScheffeTest(MSErr, SlcSums, SlcCount, MinF3, MaxF3, N, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if TukeyHSDChk.Checked and equal_grp then
|
|
|
|
Tukey(MSErr, DFErr, value, SlcSums, SlcCount, MinF3, MaxF3, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if TukeyBChk.Checked and equal_grp then
|
|
|
|
TukeyBTest(MSErr, DFErr, SlcSums, SlcCount, MinF3, MaxF3, value, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if TukeyKramerChk.Checked and equal_grp then
|
|
|
|
Tukey_Kramer(MSErr, DFErr, value, SlcSums, SlcCount, MinF3, MaxF3, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if NewmanKeulsChk.Checked and equal_grp then
|
|
|
|
Newman_Keuls(MSErr, DFErr, value, SlcSums, SlcCount, MinF3, MaxF3, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if BonferroniChk.Checked then
|
|
|
|
Bonferroni(SlcSums, SlcCount, variances, MinF3, MaxF3, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if OrthoContrastsChk.Checked then
|
|
|
|
Contrasts(MSErr, DFErr, SlcSums, SlcCount, MinF3, MaxF3, allAlpha, posthocAlpha, lReport);
|
|
|
|
end;
|
|
|
|
|
|
|
|
// Do simple effects for columns within each row
|
|
|
|
if (ProbF1f2 < allAlpha) then
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
if lReport.Count > 0 then
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('COMPARISONS AMONG COLUMNS WITHIN EACH ROW');
|
|
|
|
for i := 0 to NF1cells-1 do
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('ROW %d COMPARISONS',[i+1]);
|
|
|
|
|
|
|
|
// move cell sums and counts to cellsums and cellcnts
|
2020-11-10 15:11:42 +00:00
|
|
|
for j := 0 to NF2Cells-1 do
|
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
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;
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
|
|
|
|
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 NewmanKeulsChk.Checked and equal_grp then
|
|
|
|
Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, MinF2, MaxF2, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if BonferroniChk.Checked then
|
|
|
|
Bonferroni(cellsums, cellcnts, cellvars, MinF2, MaxF2, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if OrthoContrastsChk.Checked then
|
|
|
|
Contrasts(MSErr, DFErr, cellsums, cellcnts, MinF2, MaxF2, allAlpha, posthocAlpha, lReport);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
// Do simple effects for rows within each column
|
|
|
|
if (ProbF1f2 < allAlpha) then
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
if lReport.Count > 0 then
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('COMPARISONS AMONG ROWS WITHIN EACH COLUMN');
|
2020-11-10 15:11:42 +00:00
|
|
|
for j := 0 to NF2Cells-1 do
|
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('COLUMN %d COMPARISONS', [j+1]);
|
|
|
|
|
|
|
|
// move cell sums and counts to cellsums and cellcnts
|
2020-11-10 15:11:42 +00:00
|
|
|
for i := 0 to NF1Cells-1 do
|
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
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;
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
|
|
|
|
value := 1e308;
|
2020-11-10 15:11:42 +00:00
|
|
|
for i := 0 to NF1Cells-1 do
|
2020-11-10 16:46:13 +00:00
|
|
|
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 NewmanKeulsChk.Checked and equal_grp then
|
|
|
|
Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, MinF1, MaxF1, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if BonferroniChk.Checked then
|
|
|
|
Bonferroni(cellsums, cellcnts, cellvars, MinF1, MaxF1, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if OrthoContrastsChk.Checked then
|
|
|
|
Contrasts(MSErr, DFErr, cellsums, cellcnts, MinF1, MaxF1, allAlpha, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
// Do simple effects for columns within each slice
|
|
|
|
if (ProbF2F3 < allAlpha) then
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
if lReport.Count > 0 then
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('COMPARISONS AMONG COLUMNS WITHIN EACH SLICE');
|
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
for k := 0 to NF3Cells-1 do
|
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('SLICE %d COMPARISONS', [k+1]);
|
|
|
|
|
|
|
|
// move cell sums and counts to cellsums and cellcnts
|
2020-11-10 15:11:42 +00:00
|
|
|
for j := 0 to NF2Cells-1 do
|
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
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;
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
value := 1e20;
|
|
|
|
for j := 1 to NF2cells 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 NewmanKeulsChk.Checked and equal_grp then
|
|
|
|
Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, MinF2, MaxF2, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if BonferroniChk.Checked then
|
|
|
|
Bonferroni(cellsums, cellcnts, cellvars, MinF2, MaxF2, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if OrthoContrastsChk.Checked then
|
|
|
|
Contrasts(MSErr, DFErr, cellsums, cellcnts, MinF2, MaxF2, allAlpha, posthocAlpha, lReport);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
// Do simple effects for rows within each slice
|
|
|
|
if (ProbF1F3 < allAlpha) then
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
if lReport.Count > 0 then
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('COMPARISONS AMONG ROWS WITHIN EACH SLICE');
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
for k := 0 to NF3Cells-1 do
|
|
|
|
begin
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('SLICE %d COMPARISONS', [k+1]);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// move cell sums and counts to cellsums and 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 := 1e20;
|
|
|
|
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 NewmanKeulsChk.Checked and equal_grp then
|
|
|
|
Newman_Keuls(MSErr, DFErr, value, cellsums, cellcnts, MinF1, MaxF1, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if BonferroniChk.Checked then
|
|
|
|
Bonferroni(cellsums, cellcnts, cellvars, MinF1, MaxF1, posthocAlpha, lReport);
|
|
|
|
|
|
|
|
if OrthoContrastsChk.Checked then
|
|
|
|
Contrasts(MSErr, DFErr, cellsums, cellcnts, MinF1, MaxF1, allAlpha, posthocAlpha, lReport);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
FPosthocReportFrame.DisplayReport(lReport);
|
|
|
|
|
|
|
|
finally
|
|
|
|
lReport.Free;
|
|
|
|
end;
|
|
|
|
|
|
|
|
PostHocPage.TabVisible := true;
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
procedure TBlksAnovaForm.ThreeWayPlot;
|
|
|
|
begin
|
|
|
|
if not ShowPlotsChk.Checked then
|
|
|
|
begin
|
|
|
|
ChartPage.TabVisible := false;
|
|
|
|
exit;
|
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
FChartFrame.Clear; // this destroys the series
|
2020-11-10 16:46:13 +00:00
|
|
|
FChartFrame.SetYTitle('Mean');
|
2020-11-10 15:11:42 +00:00
|
|
|
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;
|
2020-11-10 16:46:13 +00:00
|
|
|
|
|
|
|
FChartCombobox.Parent.Left := 0;
|
|
|
|
FChartCombobox.Parent.Visible := true;
|
2020-11-10 15:11:42 +00:00
|
|
|
PopulateChartCombobox(true);
|
|
|
|
FChartCombobox.OnChange := @SelectThreeWayPlot;
|
|
|
|
SelectThreeWayPlot(nil);
|
|
|
|
|
|
|
|
ChartPage.TabVisible := true;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
|
|
|
|
procedure TBlksAnovaForm.ThreeWayTable;
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport: TStrings;
|
|
|
|
groupsize: integer;
|
|
|
|
MinVar, MaxVar, sumvars, sumDFrecip: double;
|
|
|
|
i, j, k: integer;
|
|
|
|
XBar, V, S, RowSS, ColSS, SlcSS: double;
|
|
|
|
sumfreqlogvar, c, bartlett, cochran, hartley, chiprob: double;
|
|
|
|
problem: boolean = false;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport := TStringList.Create;
|
|
|
|
try
|
|
|
|
lReport.Add('THREE-WAY ANALYSIS OF VARIANCE');
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('Variable analyzed: %s', [DepVarEdit.Text]);
|
|
|
|
lReport.Add('Factor A (rows) variable: %s (%s levels)', [
|
|
|
|
Factor1Edit.Text, FIXED_RANDOM[Fact1Combo.ItemIndex]
|
|
|
|
]);
|
|
|
|
lReport.Add('Factor B (columns) variable: %s (%s levels)', [
|
|
|
|
Factor2Edit.Text, FIXED_RANDOM[Fact2Combo.ItemIndex]
|
|
|
|
]);
|
|
|
|
lReport.Add('Factor C (slices) variable: %s (%s levels)', [
|
|
|
|
Factor3Edit.Text, FIXED_RANDOM[Fact3Combo.ItemIndex]
|
|
|
|
]);
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add( '--------------------------------------------------------------------------------');
|
|
|
|
lReport.Add( 'SOURCE D.F. SS MS F PROB.> F Omega Squared');
|
|
|
|
lReport.Add( '------------- ---- ---------- ---------- ---------- -------- -------------');
|
|
|
|
if OKTerms[1]and OKTerms[8] then
|
|
|
|
lReport.Add('Among Rows %4.0f %10.3f %10.3f %10.3f %8.3f %10.3f', [DFF1, SSF1, MSF1, FF1, ProbF1, OmegaF1])
|
|
|
|
else
|
|
|
|
lReport.Add('Among Rows %4.0f %10.3f %10.3f --- error ---', [DFF1, SSF1, MSF1 ]);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if OKTerms[2] and OKTerms[9] then
|
|
|
|
lReport.Add('Among Columns %4.0f %10.3f %10.3f %10.3f %8.3f %10.3f', [DFF2, SSF2, MSF2, FF2, ProbF2, OmegaF2])
|
|
|
|
else
|
|
|
|
lReport.Add('Among Columns %4.0f %10.3f %10.3f --- error ---', [DFF2, SSF2, MSF2]);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if OKTerms[3] and OKTerms[10] then
|
|
|
|
lReport.Add('Among Slices %4.0f %10.3f %10.3f %10.3f %8.3f %10.3f', [DFF3, SSF3, MSF3, FF3, ProbF3, OmegaF3])
|
|
|
|
else
|
|
|
|
lReport.Add('Among Slices %4.0f %10.3f %10.3f --- error ---', [DFF3, SSF3, MSF3]);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport.Add( 'A x B Inter. %4.0f %10.3f %10.3f %10.3f %8.3f %10.3f', [DFF1F2, SSF1F2, MSF1F2, FF1F2, ProbF1F2, OmegaF1F2]);
|
|
|
|
lReport.Add( 'A x C Inter. %4.0f %10.3f %10.3f %10.3f %8.3f %10.3f', [DFF1F3, SSF1F3, MSF1F3, FF1F3, ProbF1F3, OmegaF1F3]);
|
|
|
|
lReport.Add( 'B x C Inter. %4.0f %10.3f %10.3f %10.3f %8.3f %10.3f', [DFF2F3, SSF2F3, MSF2F3, FF2F3, ProbF2F3, OmegaF2F3]);
|
|
|
|
lReport.Add( 'AxBxC Inter. %4.0f %10.3f %10.3f %10.3f %8.3f %10.3f', [DFF1F2F3, SSF1F2F3, MSF1F2F3, FF1F2F3, ProbF1F2F3, OmegaF1F2F3]);
|
|
|
|
lReport.Add( 'Within Groups %4.0f %10.3f %10.3f', [DFErr, SSErr, MSErr]);
|
|
|
|
lReport.Add( 'Total %4.0f %10.3f %10.3f', [DFTot, SSDep, MSDep]);
|
|
|
|
lReport.Add( '--------------------------------------------------------------------------------');
|
|
|
|
lReport.Add( '');
|
|
|
|
lReport.Add( 'Omega squared for combined effects: %.3f', [Omega]);
|
|
|
|
lReport.Add( '');
|
|
|
|
if (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 0) and (Fact3Combo.ItemIndex = 0) then
|
|
|
|
lReport.Add('Note: MSErr denominator for all F ratios.')
|
|
|
|
else
|
|
|
|
if (Fact1Combo.ItemIndex = 1) and (Fact2Combo.ItemIndex = 1) and (Fact3Combo.ItemIndex = 1) then
|
2020-06-23 17:16:32 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport.Add('Note: Error term for A is MSAxB + MSAxC - MSAxBxC');
|
|
|
|
lReport.Add('Error term for B is MSAxB + MSBxC - MSAxBxC');
|
|
|
|
lReport.Add('Error term for C is MSAxC + MSBxC - MSAxBxC');
|
|
|
|
lReport.Add('Error term for AxB, AxC and BxC is MSAxBxC');
|
|
|
|
lReport.Add('Error term for AxBxC is MSErr.');
|
|
|
|
end else
|
|
|
|
if (Fact1Combo.ItemIndex = 1) and (Fact2Combo.ItemIndex = 0) and (Fact3Combo.ItemIndex = 0) then
|
|
|
|
begin
|
|
|
|
lReport.Add('Note: Error term for A is MSErr');
|
|
|
|
lReport.Add('Note: Error term for B is MSAxB');
|
|
|
|
lReport.Add('Note: Error term for C is MSAxC');
|
|
|
|
lReport.Add('Note: Error term for AxB is MSErr');
|
|
|
|
lReport.Add('Note: Error term for AxC is MSErr');
|
|
|
|
lReport.Add('Note: Error term for BxC is MSAxBxC');
|
|
|
|
lReport.Add('Note: Error term for AxBxC is MSErr');
|
|
|
|
end else
|
|
|
|
if (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 1) and (Fact3Combo.ItemIndex = 0) then
|
|
|
|
begin
|
|
|
|
lReport.Add('Note: Error term for A is MSAxB');
|
|
|
|
lReport.Add('Note: Error term for B is MSErr');
|
|
|
|
lReport.Add('Note: Error term for C is MSBxC');
|
|
|
|
lReport.Add('Note: Error term for AxB is MSErr');
|
|
|
|
lReport.Add('Note: Error term for AxC is MSAxBxC');
|
|
|
|
lReport.Add('Note: Error term for BxC is MSErr');
|
|
|
|
lReport.Add('Note: Error term for AxBxC is MSErr');
|
|
|
|
end else
|
|
|
|
if (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 0) and (Fact3Combo.ItemIndex = 1) then
|
|
|
|
begin
|
|
|
|
lReport.Add('Note: Error term for A is MSAxC');
|
|
|
|
lReport.Add('Note: Error term for B is MSBxC');
|
|
|
|
lReport.Add('Note: Error term for C is MSErr');
|
|
|
|
lReport.Add('Note: Error term for AxB is MSAxBxC');
|
|
|
|
lReport.Add('Note: Error term for AxC is MSErr');
|
|
|
|
lReport.Add('Note: Error term for BxC is MSErr');
|
|
|
|
lReport.Add('Note: Error term for AxBxC is MSErr');
|
|
|
|
end else
|
|
|
|
if (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 1) and (Fact3Combo.ItemIndex = 1) then
|
|
|
|
begin
|
|
|
|
lReport.Add('Note: Error term for A is MSAxC + MSAxB - MSAxBxC');
|
|
|
|
lReport.Add('Note: Error term for B is MSBxC');
|
|
|
|
lReport.Add('Note: Error term for C is MSBxC');
|
|
|
|
lReport.Add('Note: Error term for AxB is MSAxBxC');
|
|
|
|
lReport.Add('Note: Error term for AxC is MSAxBxC');
|
|
|
|
lReport.Add('Note: Error term for BxC is MSErr');
|
|
|
|
lReport.Add('Note: Error term for AxBxC is MSErr');
|
|
|
|
end else
|
|
|
|
if (Fact1Combo.ItemIndex = 1) and (Fact2Combo.ItemIndex = 0) and (Fact3Combo.ItemIndex = 1) then
|
|
|
|
begin
|
|
|
|
lReport.Add('Note: Error term for A is MSAxC');
|
|
|
|
lReport.Add('Note: Error term for B is MSBxC + MSAxB - MSAxBxC');
|
|
|
|
lReport.Add('Note: Error term for C is MSAxC');
|
|
|
|
lReport.Add('Note: Error term for AxB is MSAxBxC');
|
|
|
|
lReport.Add('Note: Error term for AxC is MSErr');
|
|
|
|
lReport.Add('Note: Error term for BxC is MSAxBxC');
|
|
|
|
lReport.Add('Note: Error term for AxBxC is MSErr');
|
|
|
|
end else
|
|
|
|
if (Fact1Combo.ItemIndex = 1) and (Fact2Combo.ItemIndex = 1) and (Fact3Combo.ItemIndex = 0) then
|
2020-06-23 17:16:32 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport.Add('Note: Error term for A is MSAxB');
|
|
|
|
lReport.Add('Note: Error term for B is MSAxB');
|
|
|
|
lReport.Add('Note: Error term for C is MSBxC + MSAxC - MSAxBxC');
|
|
|
|
lReport.Add('Note: Error term for AxB is MSErr');
|
|
|
|
lReport.Add('Note: Error term for AxC is MSAxBxC');
|
|
|
|
lReport.Add('Note: Error term for BxC is MSAxBxC');
|
|
|
|
lReport.Add('Note: Error term for AxBxC is MSErr');
|
2020-06-23 17:16:32 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
for i := 1 to 10 do
|
|
|
|
if not OKTerms[i] then
|
|
|
|
problem := true;
|
|
|
|
|
|
|
|
if problem then
|
2020-06-23 17:16:32 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('An error occurred due to either an estimate of MS being negative');
|
|
|
|
lReport.Add('or the degrees of freedom being zero. This may occur in a design');
|
|
|
|
lReport.Add('with random factors using the expected values for an exact F-test.');
|
|
|
|
lReport.Add('Quasi-F statistics may be employed where this problem exists. See');
|
|
|
|
lReport.Add('Winer, B.J., "Statistical Principles in Experimental Design, 1962');
|
|
|
|
lReport.Add('Section 5.15, pages 199-202 and Glass, G.V. and Stanley, J.C.,');
|
|
|
|
lReport.Add('1970, Section 18.10, pages 481-482.');
|
2020-06-23 17:16:32 +00:00
|
|
|
end;
|
2020-11-09 15:39:10 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add(DIVIDER_AUTO);
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('DESCRIPTIVE STATISTICS');
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('-------------------------------------------------------------');
|
|
|
|
lReport.Add('GROUP ROW COL SLICE N MEAN VARIANCE STD.DEV.');
|
|
|
|
lReport.Add('----- --- --- ----- ----- -------- ---------- --------');
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Display cell means, variances, standard deviations
|
|
|
|
groupsize := NCnt[1, 1, 1];
|
|
|
|
equal_grp := true;
|
|
|
|
MaxVar := -1E308;
|
|
|
|
MinVar := 1E308;
|
|
|
|
sumVars := 0.0;
|
|
|
|
sumFreqLogVar := 0.0;
|
|
|
|
sumDFRecip := 0.0;
|
|
|
|
for i := 0 to NoGrpsA-1 do
|
2020-11-09 21:52:26 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
for j := 0 to NoGrpsB-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
for k := 0 to NoGrpsC-1 do
|
|
|
|
begin
|
|
|
|
XBar := WSum[i, j, k] / NCnt[i, j, k];
|
|
|
|
V := (WX2[i, j, k] - sqr(WSum[i, j, k]) / NCnt[i, j, k]) / (NCnt[i, j, k] - 1);
|
|
|
|
S := sqrt(V);
|
|
|
|
sumVars := sumVars + V;
|
|
|
|
if V > MaxVar then MaxVar := V;
|
|
|
|
if V < MinVar then MinVar := V;
|
|
|
|
sumDFRecip := sumDFRecip + (1.0 / (NCnt[i, j, k] - 1));
|
|
|
|
sumfreqLogVar := sumFreqLogVar + (NCnt[i, j, k] - 1) * ln(V);
|
|
|
|
if NCnt[i, j, k] <> groupsize then equal_grp := false;
|
|
|
|
lReport.Add('Cell %3d %3d %5d %5d %8.3f %10.3f %8.3f', [MinF1+i, MinF2+j, MinF3+k, NCnt[i, j, k], XBar, V, S]);
|
|
|
|
end;
|
2020-11-09 21:52:26 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
//Display Row means, variances, standard deviations
|
|
|
|
for i := 0 to NoGrpsA-1 do
|
2020-11-09 21:52:26 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
XBar := RowSums[i] / RowCount[i];
|
|
|
|
RowSS := 0.0;
|
2020-11-09 21:52:26 +00:00
|
|
|
for j := 0 to NoGrpsB-1 do
|
2020-11-10 16:46:13 +00:00
|
|
|
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 %5d %8.3f %10.3f %8.3f', [MinF1+i, RowCount[i], xBar, V, s]);
|
2020-11-09 21:52:26 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
//Display means, variances and standard deviations for columns
|
|
|
|
for j := 0 to NoGrpsB-1 do
|
2020-11-09 21:52:26 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
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 %5d %8.3f %10.3f %8.3f', [MinF2+j, ColCount[j], xBar, V, S]);
|
2020-11-09 21:52:26 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
//Display means, variances and standard deviations for slices
|
|
|
|
for k := 0 to NoGrpsC-1 do
|
2020-11-09 21:52:26 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
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 %5d %5d %8.3f %10.3f %8.3f', [MinF3+k, SlcCount[k], xBar, V,S]);
|
|
|
|
end;
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport.Add('-------------------------------------------------------------');
|
|
|
|
lReport.Add('TOTAL %5d %8.3f %10.3f %8.3f', [N, MeanDep, MSDep, sqrt(MSDep)]);
|
|
|
|
lReport.Add('-------------------------------------------------------------');
|
|
|
|
lReport.Add('');
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
c := 1.0 + (1.0 / (3.0 * NoGrpsA * NoGrpsB * NoGrpsC - 1)) * (sumDFrecip - (1.0 / DFErr));
|
|
|
|
bartlett := (2.303 / c) * ((DFErr * ln(MSErr)) - SumFreqLogVar);
|
|
|
|
chiProb := ChiSquaredProb(bartlett, round(NoGrpsA * NoGrpsB * NoGrpsC - 1));
|
|
|
|
cochran := MaxVar / SumVars;
|
|
|
|
hartley := MaxVar / MinVar;
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport.Add(DIVIDER);
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('TESTS FOR HOMOGENEITY OF VARIANCE');
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('Hartley Fmax test statistic: %8.3f with %d and %d degrees of freedom.', [hartley, NoGrpsA*NoGrpsB, groupsize-1]);
|
|
|
|
lReport.Add('Cochran C statistic: %8.3f with %d and %d degrees of freedom.', [cochran, NoGrpsA*NoGrpsB, groupsize-1]);
|
|
|
|
lReport.Add('Bartlett Chi-square statistic: %8.3f with %d degrees of freedom; probability > value: %.3f', [bartlett, NoGrpsA*NoGrpsB-1, 1-chiProb]);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
FReportFrame.DisplayReport(lReport);
|
2020-11-09 21:52:26 +00:00
|
|
|
finally
|
|
|
|
lReport.Free;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-09 21:52:26 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.TwoWayContrasts;
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-11-10 15:11:42 +00:00
|
|
|
lReport: TStrings;
|
2020-11-10 16:46:13 +00:00
|
|
|
i, j: integer;
|
2020-11-09 15:39:10 +00:00
|
|
|
value: double;
|
|
|
|
variances: DblDyneVec = nil;
|
2020-11-10 16:46:13 +00:00
|
|
|
RowSS, ColSS: double;
|
2020-11-10 15:11:42 +00:00
|
|
|
totalCells: Integer;
|
2020-11-10 16:46:13 +00:00
|
|
|
allAlpha, posthocAlpha: Double;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 15:11:42 +00:00
|
|
|
if not (ScheffeChk.Checked or TukeyHSDChk.Checked or TukeyBChk.Checked or
|
|
|
|
TukeyKramerChk.Checked or NewmanKeulsChk.Checked or
|
|
|
|
BonferroniChk.Checked or OrthoContrastsChk.Checked) then
|
|
|
|
begin
|
|
|
|
PostHocPage.TabVisible := false;
|
|
|
|
exit;
|
|
|
|
end;
|
2020-11-09 15:39:10 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
allAlpha := StrToFloat(OverallAlphaEdit.Text);
|
|
|
|
posthocAlpha := StrToFloat(PostAlphaEdit.Text);
|
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
totalCells := NF1Cells + NF2Cells + NF3Cells;
|
|
|
|
SetLength(variances, totalCells);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
lReport := TStringList.Create;
|
|
|
|
try
|
|
|
|
// Do row comparisons
|
2020-11-10 16:46:13 +00:00
|
|
|
if (NF1cells > 2) and (ProbF1 < allAlpha) and (Fact2Combo.ItemIndex = 0) then
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
|
|
|
for i := 0 to NoGrpsA-1 do
|
|
|
|
begin
|
|
|
|
RowSS := 0.0;
|
2020-11-10 16:46:13 +00:00
|
|
|
for j := 0 to NoGrpsB-1 do RowSS := RowSS + vars[i,j];
|
2020-11-10 15:11:42 +00:00
|
|
|
variances[i] := (RowSS - sqr(RowSums[i]) / RowCount[i]) / (RowCount[i] - 1);
|
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
lReport.Add('COMPARISONS AMONG ROWS');
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// Get smallest group size
|
|
|
|
value := 1e308;
|
2020-11-10 15:11:42 +00:00
|
|
|
for i := 0 to NF1Cells-1 do
|
|
|
|
if RowCount[i] < value then value := RowCount[i];
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
if ScheffeChk.Checked then
|
2020-11-10 16:46:13 +00:00
|
|
|
ScheffeTest(MSErr, RowSums, RowCount, minf1, maxf1, N, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if TukeyHSDChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
Tukey(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if TukeyBChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
TukeyBTest(MSErr, DFErr, RowSums, RowCount, minf1, maxf1, value, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if TukeyKramerChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
Tukey_Kramer(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if NewmanKeulsChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
Newman_Keuls(MSErr, DFErr, value, RowSums, RowCount, minf1, maxf1, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if BonferroniChk.Checked then
|
2020-11-10 16:46:13 +00:00
|
|
|
Bonferroni(RowSums, RowCount, variances, minf1, maxf1, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if OrthoContrastsChk.Checked then
|
2020-11-10 16:46:13 +00:00
|
|
|
Contrasts(MSErr, DFErr, RowSums, RowCount, minf1, maxf1, AllAlpha, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
// Do column comparisons
|
2020-11-10 16:46:13 +00:00
|
|
|
if (NF2Cells > 2) and (ProbF2 < allAlpha) and (Fact2Combo.ItemIndex = 0) then
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
|
|
|
for j := 0 to NoGrpsB-1 do
|
|
|
|
begin
|
|
|
|
ColSS := 0.0;
|
|
|
|
for i := 0 to NoGrpsA-1 do
|
2020-11-10 16:46:13 +00:00
|
|
|
ColSS := ColSS + vars[i,j];
|
2020-11-10 15:11:42 +00:00
|
|
|
variances[j] := (ColSS - sqr(ColSums[j]) / ColCount[j]) / (ColCount[j] - 1);
|
2020-11-10 16:46:13 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if lReport.Count <> 0 then
|
2020-11-10 15:11:42 +00:00
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('COMPARISONS AMONG COLUMNS');
|
2020-11-10 16:46:13 +00:00
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
value := 1e308;
|
2020-11-10 16:46:13 +00:00
|
|
|
for i := 0 to NF2cells-1 do
|
2020-11-10 15:11:42 +00:00
|
|
|
if ColCount[i] < value then value := ColCount[i];
|
|
|
|
|
|
|
|
if ScheffeChk.Checked then
|
2020-11-10 16:46:13 +00:00
|
|
|
ScheffeTest(MSErr, ColSums, ColCount, minf2, maxf2, N, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if TukeyHSDChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
Tukey(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if TukeyBChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
TukeyBTest(MSErr, DFErr, ColSums, ColCount, minf2, maxf2, value, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if TukeyKramerChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
Tukey_Kramer(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if NewmanKeulsChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
Newman_Keuls(MSErr, DFErr, value, ColSums, ColCount, minf2, maxf2, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if BonferroniChk.Checked then
|
2020-11-10 16:46:13 +00:00
|
|
|
Bonferroni(ColSums, ColCount, variances, minf2, maxf2, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if OrthoContrastsChk.Checked then
|
2020-11-10 16:46:13 +00:00
|
|
|
Contrasts(MSErr, DFErr, ColSums, ColCount, minf2, maxf2, AllAlpha, postHocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// do simple effects for columns within each row
|
|
|
|
if (ProbF3 < allAlpha) and (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 0) then
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
if lReport.Count <> 0 then
|
2020-11-10 15:11:42 +00:00
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('COMPARISONS AMONG COLUMNS WITHIN EACH ROW');
|
2020-11-10 16:46:13 +00:00
|
|
|
for i := 0 to NF1Cells-1 do
|
2020-11-10 15:11:42 +00:00
|
|
|
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
|
2020-11-10 16:46:13 +00:00
|
|
|
cellSums[j] := Sums[i,j];
|
|
|
|
cellCnts[j] := Counts[i,j];
|
|
|
|
cellVars[j] := Vars[i,j];
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
value := 1e308;
|
|
|
|
for j := 0 to NF2Cells-1 do
|
2020-11-10 16:46:13 +00:00
|
|
|
if cellCnts[j] < value then value := cellCnts[j];
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if ScheffeChk.Checked then
|
2020-11-10 16:46:13 +00:00
|
|
|
ScheffeTest(MSErr, cellSums, cellCnts, MinF2, MaxF2, N, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if TukeyHSDChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
Tukey(MSErr, DFErr, value, cellSums, cellCnts, MinF2, MaxF2, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if TukeyBChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
TukeyBTest(MSErr, DFErr, cellSums, cellCnts, MinF2, MaxF2, value, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if TukeyKramerChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
Tukey_Kramer(MSErr, DFErr, value, cellSums, cellCnts, MinF2, MaxF2, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if NewmanKeulsChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
Newman_Keuls(MSErr, DFErr, value, cellSums, cellCnts, MinF2, MaxF2, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if BonferroniChk.Checked then
|
2020-11-10 16:46:13 +00:00
|
|
|
Bonferroni(cellSums, cellCnts, cellVars, MinF2, MaxF2, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if OrthoContrastsChk.Checked then
|
2020-11-10 16:46:13 +00:00
|
|
|
Contrasts(MSErr, DFErr, cellSums, cellCnts, MinF2, MaxF2, allAlpha, PostHocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
// do simple effects for rows within each column
|
|
|
|
if (ProbF3 < allAlpha) and (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 0) then
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
|
|
|
if lReport.Count > 0 then
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('COMPARISONS AMONG ROWS WITHIN EACH COLUMN');
|
|
|
|
for j := 0 to NF2Cells-1 do
|
2020-11-10 15:11:42 +00:00
|
|
|
begin
|
|
|
|
lReport.Add('');
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport.Add('COLUMN %d COMPARISONS', [j+1]);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
// move cell sums and counts to cellsums and cellcnts
|
|
|
|
for i := 0 to NF1Cells-1 do
|
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
cellSums[i] := Sums[i,j];
|
|
|
|
cellCnts[i] := Counts[i,j];
|
|
|
|
cellVars[i] := Vars[i,j];
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
value := 1e308;
|
2020-11-10 15:11:42 +00:00
|
|
|
for i := 0 to NF1Cells-1 do
|
2020-11-10 16:46:13 +00:00
|
|
|
if cellCnts[j] < value then value := cellCnts[j];
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if ScheffeChk.Checked then
|
2020-11-10 16:46:13 +00:00
|
|
|
ScheffeTest(MSErr, cellSums, cellCnts, MinF1, MaxF1, N, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if TukeyHSDChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
Tukey(MSErr, DFErr, value, cellSums, cellCnts, MinF1, MaxF1, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if TukeyBChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
TukeyBTest(MSErr, DFErr, cellSums, cellCnts, MinF1, MaxF1, value, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if TukeyKramerChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
Tukey_Kramer(MSErr, DFErr, value, cellSums, cellCnts, MinF1, MaxF1, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if NewmanKeulsChk.Checked and equal_grp then
|
2020-11-10 16:46:13 +00:00
|
|
|
Newman_Keuls(MSErr, DFErr, value, cellSums, cellCnts, MinF1, MaxF1, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if BonferroniChk.Checked then
|
2020-11-10 16:46:13 +00:00
|
|
|
Bonferroni(cellSums, cellCnts, cellVars, MinF1, MaxF1, posthocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
|
|
|
|
if OrthoContrastsChk.Checked then
|
2020-11-10 16:46:13 +00:00
|
|
|
Contrasts(MSErr, DFErr, cellSums, cellCnts, MinF1, MaxF1, allAlpha, postHocAlpha, lReport);
|
2020-11-10 15:11:42 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
FPosthocReportFrame.DisplayReport(lReport);
|
|
|
|
finally
|
|
|
|
lReport.Free;
|
|
|
|
end;
|
|
|
|
|
|
|
|
PostHocPage.TabVisible := true;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.TwoWayPlot;
|
|
|
|
begin
|
|
|
|
if not ShowPlotsChk.Checked then
|
|
|
|
begin
|
|
|
|
ChartPage.TabVisible := false;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
FChartFrame.Clear;
|
|
|
|
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;
|
|
|
|
{$ENDIF}
|
|
|
|
end;
|
|
|
|
if Plot3DChk.Checked then
|
|
|
|
FSeries.Depth := 20;
|
|
|
|
|
|
|
|
FChartCombobox.Parent.Left := 0;
|
|
|
|
FChartCombobox.Parent.Visible := true;
|
|
|
|
PopulateChartCombobox(false);
|
|
|
|
FChartCombobox.OnChange := @SelectTwoWayPlot;
|
|
|
|
SelectTwoWayPlot(nil);
|
|
|
|
|
|
|
|
ChartPage.TabVisible := true;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TBlksAnovaForm.TwoWayTable;
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport: TStrings;
|
|
|
|
groupsize: integer;
|
|
|
|
MinVar, MaxVar, sumvars, sumDFrecip: double;
|
|
|
|
i, j: integer;
|
|
|
|
XBar, V, S, RowSS, ColSS: double;
|
|
|
|
sumfreqlogvar, c, bartlett, cochran, hartley, chiprob: double;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
lReport := TStringList.Create;
|
|
|
|
try
|
|
|
|
lReport.Add('TWO-WAY ANALYSIS OF VARIANCE');
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('Variable analyzed: %s', [DepVarEdit.Text]);
|
|
|
|
lReport.Add('Factor A (rows) variable: %s (%s levels)',[
|
|
|
|
Factor1Edit.Text, FIXED_RANDOM[Fact1Combo.ItemIndex]
|
|
|
|
]);
|
|
|
|
lReport.Add('Factor B (columns) variable: %s (%s levels)', [
|
|
|
|
Factor2Edit.Text, FIXED_RANDOM[Fact2Combo.ItemIndex]
|
|
|
|
]);
|
|
|
|
lReport.Add('');
|
|
|
|
|
|
|
|
lReport.Add( '--------------------------------------------------------------------------------');
|
|
|
|
lReport.Add( 'SOURCE D.F. SS MS F PROB.> F Omega Squared');
|
|
|
|
lReport.Add( '------------- ---- ---------- ---------- ---------- -------- -------------');
|
|
|
|
lReport.Add( 'Among Rows %4.0f %10.3f %10.3f %10.3f %8.3f %10.3f', [DFF1, SSF1, MSF1, FF1, ProbF1, OmegaF1]);
|
|
|
|
lReport.Add( 'Among Columns %4.0f %10.3f %10.3f %10.3f %8.3f %10.3f', [DFF2, SSF2, MSF2, FF2, ProbF2, OmegaF2]);
|
|
|
|
lReport.Add( 'Interaction %4.0f %10.3f %10.3f %10.3f %8.3f %10.3f', [DFF1F2, SSF1F2, MSF1F2, FF1F2, ProbF1F2, OmegaF1F2]);
|
|
|
|
lReport.Add( 'Within Groups %4.0f %10.3f %10.3f', [DFErr, SSErr, MSErr]);
|
|
|
|
lReport.Add( 'Total %4.0f %10.3f %10.3f', [DFTot, SSDep, MSDep]);
|
|
|
|
lReport.Add( '--------------------------------------------------------------------------------');
|
|
|
|
lReport.Add( '');
|
|
|
|
lReport.Add('Omega squared for combined effects; %8.3f', [Omega]);
|
|
|
|
lReport.Add('');
|
|
|
|
if (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 0) then
|
|
|
|
lReport.Add('Note: Denominator of F ratio is MSErr');
|
|
|
|
if (Fact1Combo.ItemIndex = 1) and (Fact2Combo.ItemIndex = 1) then
|
|
|
|
lReport.Add('Note: Denominator of F ratio is MSAxB');
|
|
|
|
if (Fact1Combo.ItemIndex = 0) and (Fact2Combo.ItemIndex = 1) then
|
|
|
|
begin
|
|
|
|
lReport.Add('Note: Denominator of F ratio for A is MSAxB');
|
|
|
|
lReport.Add(' and denominator for B and AxB is MSErr');
|
|
|
|
end;
|
|
|
|
if (Fact1Combo.ItemIndex = 1) and (Fact2Combo.ItemIndex = 0) then
|
|
|
|
begin
|
|
|
|
lReport.Add('Note: Denominator of F ratio for B is MSAxB');
|
|
|
|
lReport.Add('and denominator for A and AxB is MSErr');
|
|
|
|
end;
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add(DIVIDER_AUTO);
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('DESCRIPTIVE STATISTICS');
|
|
|
|
// lReport.Add('');
|
|
|
|
lReport.Add('------------------------------------------------------');
|
|
|
|
lReport.Add('GROUP Row Col. N MEAN VARIANCE STD.DEV.');
|
|
|
|
lReport.Add('----- --- ---- ----- --------- -------- --------');
|
|
|
|
groupsize := counts[0, 0];
|
|
|
|
equal_grp := true;
|
|
|
|
MaxVar := 0.0;
|
|
|
|
MinVar := 1e20;
|
|
|
|
sumvars := 0.0;
|
|
|
|
sumfreqlogvar := 0.0;
|
|
|
|
sumDFrecip := 0.0;
|
|
|
|
|
|
|
|
// Display cell means, variances, standard deviations
|
|
|
|
V := 0.0;
|
|
|
|
XBar := 0.0;
|
|
|
|
S := 0.0;
|
|
|
|
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] - ( (sums[i,j] * 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));
|
|
|
|
sumfreqlogvar := sumfreqlogvar + ((counts[i,j] - 1) * ln(V));
|
|
|
|
if counts[i,j] <> groupsize then equal_grp := false;
|
|
|
|
end;
|
|
|
|
lReport.Add('Cell %3d %3d %4d %9.3f %8.3f %8.3f', [MinF1+i, MinF2+j, counts[i,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];
|
|
|
|
RowSS := 0.0;
|
|
|
|
for j := 0 to NoGrpsB-1 do RowSS := RowSS + vars[i,j];
|
|
|
|
V := RowSS - (RowSums[i] * RowSums[i] / RowCount[i]);
|
|
|
|
V := V / (RowCount[i] - 1);
|
|
|
|
S := sqrt(V);
|
|
|
|
lReport.Add('Row %3d %4d %9.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
|
|
|
|
XBar := ColSums[j] / ColCount[j];
|
|
|
|
ColSS := 0.0;
|
|
|
|
for i := 0 to NoGrpsA-1 do ColSS := ColSS + vars[i,j];
|
|
|
|
if ColCount[j] > 0 then V := ColSS - (ColSums[j] * ColSums[j] / ColCount[j]);
|
|
|
|
if ColCount[j] > 1 then V := V / (ColCount[j] - 1);
|
|
|
|
if V > 0.0 then S := sqrt(V);
|
|
|
|
lReport.Add('Col %3d %4d %9.3f %8.3f %8.3f', [minf2+j, ColCount[j], XBar, V, S]);
|
|
|
|
end;
|
|
|
|
|
|
|
|
lReport.Add('------------------------------------------------------');
|
|
|
|
lReport.Add('TOTAL %4d %9.3f %8.3f %8.3f', [N, MeanDep, MSDep, sqrt(MSDep)]);
|
|
|
|
lReport.Add('------------------------------------------------------');
|
|
|
|
lReport.Add('');
|
|
|
|
|
|
|
|
c := 1.0 + (1.0 / (3.0 * NoGrpsA * NoGrpsB - 1.0)) * (sumDFrecip - (1.0 / DFErr));
|
|
|
|
bartlett := (2.303 / c) * ((DFErr * ln(MSErr)) - sumfreqlogvar);
|
|
|
|
chiprob := 1.0 - ChiSquaredProb(bartlett, round(NoGrpsA * NoGrpsB - 1));
|
|
|
|
cochran := maxvar / sumvars;
|
|
|
|
hartley := maxvar / minvar;
|
|
|
|
|
|
|
|
lReport.Add(DIVIDER_AUTO);
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('TESTS FOR HOMOGENEITY OF VARIANCE');
|
|
|
|
lReport.Add(''); //DIVIDER_SMALL_AUTO);
|
|
|
|
lReport.Add('Hartley Fmax test statistic: %8.3f with %d and %d degrees of freedom.', [hartley, NoGrpsA*NoGrpsB, groupsize-1]);
|
|
|
|
lReport.Add('Cochran C statistic: %8.3f with %d and %d degrees of freedom.', [cochran, NoGrpsA*NoGrpsB, groupsize - 1]);
|
|
|
|
lReport.Add('Bartlett Chi-square statistic: %8.3f with %d degrees of freedom; prob. > value: %.3f', [bartlett, NoGrpsA*NoGrpsB - 1, chiprob]);
|
|
|
|
// lReport.Add(DIVIDER_AUTO);
|
|
|
|
|
|
|
|
FReportFrame.DisplayReport(lReport);
|
|
|
|
finally
|
|
|
|
lReport.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TBlksAnovaForm.UpdateBtnStates;
|
|
|
|
begin
|
|
|
|
inherited;
|
|
|
|
|
|
|
|
if FPosthocReportFrame <> nil then
|
|
|
|
FPostHocReportFrame.UpdateBtnStates;
|
|
|
|
|
|
|
|
DepIn.Enabled := (VarList.ItemIndex > -1) and (DepVarEdit.Text = '');
|
|
|
|
DepOut.Enabled := DepVarEdit.Text <> '';
|
|
|
|
|
|
|
|
Fact1In.Enabled := (VarList.ItemIndex > -1) and (Factor1Edit.Text = '');
|
|
|
|
Fact1Out.Enabled := Factor1Edit.Text <> '';
|
|
|
|
|
|
|
|
Fact2In.Enabled := (VarList.ItemIndex > -1) and (Factor2Edit.Text = '');
|
|
|
|
Fact2Out.Enabled := Factor2Edit.Text <> '';
|
|
|
|
|
|
|
|
Fact3In.Enabled := (VarList.ItemIndex > -1) and (Factor3Edit.Text = '');
|
|
|
|
Fact3Out.Enabled := Factor3Edit.Text <> '';
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function TBlksAnovaForm.Validate(out AMsg: String; out AControl: TWinControl): Boolean;
|
|
|
|
var
|
|
|
|
a: Double;
|
|
|
|
begin
|
|
|
|
Result := false;
|
|
|
|
|
|
|
|
if DepVarEdit.Text = '' then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
AMsg := 'Dependent variable not specified.';
|
|
|
|
AControl := VarList;
|
|
|
|
exit;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if Factor1Edit.Text = '' then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
AMsg := 'Factor 1 variable not specified.';
|
|
|
|
AControl := VarList;
|
|
|
|
exit;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if (Factor2Edit.Text = '') and (Factor3Edit.Text <> '') then
|
|
|
|
begin
|
|
|
|
AMsg := 'A two-way ANOVA needs factors 1 and 2 (not 3), a three-way analysis needs all factors.';
|
|
|
|
AControl := VarList;
|
|
|
|
exit;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if OverallAlphaEdit.Text = '' then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
AMsg := 'Overall alpha level not specified.';
|
|
|
|
AControl := OverallAlphaEdit;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
if not TryStrToFloat(OverallAlphaEdit.Text, a) or (a <= 0) or (a >= 1) then
|
|
|
|
begin
|
|
|
|
AMsg := 'Overall alpha level is not a valid number between 0 and 1.';
|
|
|
|
AControl := OverallAlphaEdit;
|
|
|
|
exit;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
if PostAlphaEdit.Text = '' then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
AMsg := 'Post-hoc alpha level not specified.';
|
|
|
|
AControl := PostAlphaEdit;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
if not TryStrToFloat(PostAlphaEdit.Text, a) or (a <= 0) or (a >= 1) then
|
|
|
|
begin
|
|
|
|
AMsg := 'Post-hoc alpha level is not a valid number between 0 and 1.';
|
|
|
|
AControl := PostAlphaEdit;
|
|
|
|
exit;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
Result := true;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.VarChange(Sender: TObject);
|
|
|
|
begin
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.VarListDblClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
index: Integer;
|
|
|
|
s: String;
|
|
|
|
begin
|
|
|
|
index := VarList.ItemIndex;
|
|
|
|
if index > -1 then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-11-10 16:46:13 +00:00
|
|
|
s := VarList.Items[index];
|
|
|
|
if DepVarEdit.Text = '' then
|
|
|
|
DepVarEdit.Text := s
|
|
|
|
else if Factor1Edit.Text = '' then
|
|
|
|
Factor1Edit.Text := s
|
|
|
|
else if Factor2Edit.Text = '' then
|
|
|
|
Factor2Edit.Text := s
|
|
|
|
else if Factor3Edit.Text = '' then
|
|
|
|
Factor3Edit.Text := s;
|
|
|
|
VarList.Items.Delete(index);
|
|
|
|
UpdateBtnStates;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-11-10 16:46:13 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
|
2020-11-10 16:46:13 +00:00
|
|
|
procedure TBlksAnovaForm.VarListSelectionChange(Sender: TObject; User: boolean);
|
|
|
|
begin
|
|
|
|
UpdateBtnStates;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-11-10 15:11:42 +00:00
|
|
|
|
2020-11-09 17:34:25 +00:00
|
|
|
procedure TBlksAnovaForm.WelchOneWay(AReport: TStrings);
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-06-23 18:16:25 +00:00
|
|
|
i, intValue: integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
W, v, barx, numerator, denominator: double;
|
|
|
|
wj: array[1..50] of double;
|
|
|
|
c1: array[1..50] of double;
|
|
|
|
barxj: array[1..50] of double;
|
|
|
|
sumc1: double;
|
|
|
|
fdegfree, term1, term2, term3: double;
|
2020-11-09 15:39:10 +00:00
|
|
|
X, Xsq: Double;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
|
|
|
for i := 1 to 50 do
|
|
|
|
begin
|
|
|
|
wj[i] := 0.0;
|
|
|
|
c1[i] := 0.0;
|
|
|
|
barxj[i] := 0.0;
|
|
|
|
end;
|
|
|
|
|
|
|
|
for i := 1 to NoCases do
|
|
|
|
begin
|
2020-11-09 15:39:10 +00:00
|
|
|
if not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected) then continue;
|
|
|
|
intvalue := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[1], i])));
|
2020-06-23 17:41:18 +00:00
|
|
|
// X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[DepVarCol,i]));
|
2020-06-23 18:16:25 +00:00
|
|
|
intvalue := intvalue - minf1;
|
|
|
|
cellcnts[intvalue] := 0;
|
|
|
|
cellsums[intvalue] := 0.0;
|
|
|
|
cellvars[intvalue] := 0.0;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
MeanDep := 0.0;
|
|
|
|
SSDep := 0.0;
|
|
|
|
SSF1 := 0.0;
|
|
|
|
MSErr := 0.0;
|
|
|
|
N := 0;
|
|
|
|
|
|
|
|
for i := 1 to NoCases do
|
|
|
|
begin
|
2020-11-09 15:39:10 +00:00
|
|
|
if not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected) then continue;
|
|
|
|
intvalue := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[1], i])));
|
|
|
|
X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[0], i]));
|
|
|
|
Xsq := X*X;
|
2020-06-23 18:16:25 +00:00
|
|
|
intvalue := intvalue - minf1;
|
|
|
|
cellcnts[intvalue] := cellcnts[intvalue] + 1;
|
|
|
|
cellsums[intvalue] := cellsums[intvalue] + X;
|
2020-11-09 15:39:10 +00:00
|
|
|
cellvars[intvalue] := cellvars[intvalue] + Xsq;
|
2020-03-30 18:01:44 +00:00
|
|
|
MeanDep := MeanDep + X;
|
2020-11-09 15:39:10 +00:00
|
|
|
SSDep := SSDep + Xsq;
|
2020-06-23 18:16:25 +00:00
|
|
|
barxj[intvalue+1] := barxj[intvalue+1] + X;
|
2020-03-30 18:01:44 +00:00
|
|
|
N := N + 1;
|
|
|
|
end;
|
|
|
|
|
|
|
|
DFF1 := 0;
|
|
|
|
W := 0.0;
|
|
|
|
barx := 0.0;
|
|
|
|
v := 0.0;
|
|
|
|
|
|
|
|
for i := 0 to Nf1cells-1 do
|
|
|
|
begin
|
|
|
|
if cellcnts[i] > 0 then
|
|
|
|
begin
|
|
|
|
cellvars[i] := cellvars[i] - (cellsums[i] * cellsums[i] /cellcnts[i]);
|
|
|
|
cellvars[i] := cellvars[i] / (cellcnts[i] - 1.0);
|
|
|
|
wj[i+1] := cellcnts[i] / cellvars[i];
|
|
|
|
W := W + wj[i+1];
|
|
|
|
barxj[i+1] := barxj[i+1] / cellcnts[i];
|
|
|
|
SSF1 := SSF1 + (sqr(cellsums[i]) / cellcnts[i]);
|
|
|
|
DFF1 := DFF1 + 1;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
for i := 1 to Nf1cells do
|
|
|
|
barx := barx + (wj[i] * barxj[i]);
|
|
|
|
barx := barx / W;
|
|
|
|
|
|
|
|
numerator := 0.0;
|
|
|
|
for i := 1 to Nf1cells do
|
|
|
|
numerator := numerator + (wj[i]* sqr(barxj[i]-barx));
|
|
|
|
numerator := numerator / (Nf1cells - 1.0);
|
|
|
|
|
|
|
|
denominator := 0.0;
|
|
|
|
for i := 1 to Nf1cells do
|
|
|
|
v := v + ( (1.0 /(cellcnts[i-1]-1.0)) * (sqr(1.0 - wj[i]/W)) );
|
|
|
|
v := 3.0 * v;
|
|
|
|
term1 := sqr(Nf1cells) - 1.0;
|
|
|
|
v := term1 / v;
|
|
|
|
for i := 1 to Nf1cells do
|
|
|
|
begin
|
|
|
|
term1 := 1.0 / (cellcnts[i-1] - 1.0);
|
|
|
|
term2 := sqr(1.0 - (wj[i] / W));
|
|
|
|
denominator := denominator + (term1 * term2);
|
|
|
|
end;
|
|
|
|
term1 := sqr(Nf1cells) - 1.0;
|
|
|
|
term2 := 2.0 * (Nf1cells - 2.0);
|
|
|
|
term3 := 1.0;
|
|
|
|
denominator := term3 + ((term2 / term1) * denominator);
|
|
|
|
|
|
|
|
F := numerator / denominator;
|
|
|
|
DFF1 := Nf1cells - 1;
|
|
|
|
SSF1 := SSF1 - (sqr(MeanDep) / float(N));
|
|
|
|
SSDep := SSDep - (sqr(MeanDep) / float(N));
|
|
|
|
SSErr := SSDep - SSF1;
|
|
|
|
DFTot := N - 1;
|
|
|
|
DFErr := DFTot - DFF1;
|
|
|
|
MSF1 := SSF1 / DFF1;
|
|
|
|
MeanDep := MeanDep / float(N);
|
|
|
|
|
|
|
|
sumc1 := 0.0;
|
|
|
|
for i := 0 to Nf1cells-1 do
|
|
|
|
begin
|
|
|
|
MSErr := MSErr + (((1.0 - cellcnts[i] / N) * cellvars[i])/ DFF1);
|
|
|
|
c1[i+1] := (1.0 - (cellcnts[i] / N)) * cellvars[i];
|
|
|
|
sumc1 := sumc1 + c1[i+1];
|
|
|
|
end;
|
|
|
|
|
|
|
|
for i := 1 to Nf1cells do
|
|
|
|
c1[i] := c1[i] / sumc1;
|
|
|
|
|
|
|
|
fdegfree := 0.0;
|
|
|
|
for i := 1 to Nf1cells do
|
|
|
|
fdegfree := fdegfree + (c1[i] * c1[i]) / (cellcnts[i-1]-1.0);
|
|
|
|
fdegfree := round(1.0 / fdegfree);
|
|
|
|
|
|
|
|
MSDep := SSDep / DFTot;
|
|
|
|
Omega := (SSF1 - DFF1 * MSErr) / (SSDep + MSErr);
|
|
|
|
// F := MSF1 / MSErr;
|
|
|
|
// ProbF1 := probf(F,DFF1, DFErr);
|
|
|
|
|
2020-06-23 22:10:44 +00:00
|
|
|
AReport.Add('');
|
|
|
|
AReport.Add(DIVIDER);
|
2020-03-30 18:01:44 +00:00
|
|
|
AReport.Add('WELCH ONE WAY ANALYSIS OF VARIANCE RESULTS');
|
|
|
|
AReport.Add('');
|
2020-11-09 15:39:10 +00:00
|
|
|
AReport.Add('Dependent variable is: %s', [DepVarEdit.Text]);
|
|
|
|
AReport.Add('Independent variable is: %s', [Factor1Edit.Text]);
|
2020-03-30 18:01:44 +00:00
|
|
|
AReport.Add('');
|
|
|
|
{ OutputFrm.RichEdit.Lines.Add('---------------------------------------------------------------------');
|
|
|
|
OutputFrm.RichEdit.Lines.Add('SOURCE D.F. SS MS F PROB.>F OMEGA SQR.');
|
|
|
|
OutputFrm.RichEdit.Lines.Add('---------------------------------------------------------------------');
|
|
|
|
outline := format('BETWEEN %4.0f%10.2f%10.2f%10.2f%10.2f%10.2f',
|
|
|
|
[DFF1,SSF1,MSF1,F,ProbF1,Omega]);
|
|
|
|
OutputFrm.RichEdit.Lines.Add(outline);
|
|
|
|
outline := format('WITHIN %4.0f%10.2f%10.2f',[DFErr,SSErr,MSErr]);
|
|
|
|
OutputFrm.RichEdit.Lines.Add(outline);
|
|
|
|
outline := format('TOTAL %4.0f%10.2f',[DFTot,SSDep]);
|
|
|
|
OutputFrm.RichEdit.Lines.Add(outline);
|
|
|
|
OutputFrm.RichEdit.Lines.Add('---------------------------------------------------------------------');
|
|
|
|
OutputFrm.RichEdit.Lines.Add(''); }
|
2020-06-23 22:10:44 +00:00
|
|
|
AReport.Add('Welch F statistic: %8.4f', [F]);
|
|
|
|
AReport.Add('Welch denominator degrees of freedom: %8.0f', [v]);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
probF1 := probf(F,DFF1,v);
|
2020-06-23 22:10:44 +00:00
|
|
|
AReport.Add('Welch F probability: %8.3f', [probf1]);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
WelchtTests(AReport);
|
|
|
|
end;
|
|
|
|
|
2020-11-09 17:34:25 +00:00
|
|
|
|
|
|
|
procedure TBlksAnovaForm.WelchtTests(AReport: TStrings);
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
|
|
|
i, j, NoCompares: integer;
|
2020-11-10 16:46:13 +00:00
|
|
|
t: double; // Welch t value
|
|
|
|
gnu: double; // degrees of freedom
|
|
|
|
var1, var2: double; // variance estimates for two variables
|
2020-03-30 18:01:44 +00:00
|
|
|
mean1, mean2: double; // means for two variables
|
2020-11-10 16:46:13 +00:00
|
|
|
probability: double; // t probability
|
2020-03-30 18:01:44 +00:00
|
|
|
numerator, denominator, term1, term2: double; // work values
|
2020-11-10 16:46:13 +00:00
|
|
|
v: integer; // rounded degrees of freedom
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
|
|
|
NoCompares := Nf1cells;
|
|
|
|
|
|
|
|
AReport.Add('');
|
2020-06-23 22:10:44 +00:00
|
|
|
AReport.Add(DIVIDER);
|
|
|
|
AReport.Add('WELCH T-TESTS AMONG GROUPS');
|
|
|
|
AReport.Add(DIVIDER_SMALL);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
for i := 1 to NoCompares - 1 do
|
|
|
|
begin
|
|
|
|
for j := i + 1 to NoCompares do
|
|
|
|
begin
|
|
|
|
AReport.Add('Comparison of group %d with group %d', [i, j]);
|
|
|
|
mean1 := cellsums[i-1] / cellcnts[i-1];
|
|
|
|
mean2 := cellsums[j-1] / cellcnts[j-1];
|
|
|
|
var1 := cellvars[i-1];
|
|
|
|
var2 := cellvars[j-1];
|
|
|
|
denominator := sqrt((var1 / cellcnts[i-1]) + (var2 / cellcnts[j-1]));
|
|
|
|
numerator := mean1 - mean2;
|
|
|
|
t := numerator / denominator;
|
2020-11-09 17:34:25 +00:00
|
|
|
AReport.Add('Mean %d: %8.3f', [i, mean1]);
|
|
|
|
AReport.Add('Mean %d: %8.3f', [j, mean2]);
|
2020-06-23 22:10:44 +00:00
|
|
|
AReport.Add('Welch t: %8.3f' ,[t]);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
numerator := sqr((var1 /cellcnts[i-1]) + (var2 / cellcnts[j-1]));
|
|
|
|
term1 := sqr(var1) / (sqr(cellcnts[i-1]) * (cellcnts[i-1]-1.0));
|
|
|
|
term2 := sqr(var2) / (sqr(cellcnts[j-1]) * (cellcnts[j-1]-1.0));
|
|
|
|
denominator := term1 + term2;
|
|
|
|
numerator := sqr((var1 / cellcnts[i-1]) + (var2 / cellcnts[j-1]));
|
|
|
|
gnu := numerator / denominator;
|
2020-11-09 17:34:25 +00:00
|
|
|
AReport.Add('Degrees of freedom: %8.3f', [gnu]);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
v := round(gnu);
|
2020-06-23 22:10:44 +00:00
|
|
|
AReport.Add('Rounded degrees of freedom: %8d', [v]);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-11-09 15:39:10 +00:00
|
|
|
probability := ProbT(t, gnu);
|
2020-06-23 22:10:44 +00:00
|
|
|
AReport.Add('Probability > t: %8.3f', [probability]);
|
2020-03-30 18:01:44 +00:00
|
|
|
AReport.Add('');
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-11-09 15:39:10 +00:00
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
end.
|
|
|
|
|