2020-03-30 18:01:44 +00:00
|
|
|
// Use file "abranova.laz" for testing.
|
|
|
|
|
|
|
|
unit ABRANOVAUnit;
|
|
|
|
|
|
|
|
{$mode objfpc}{$H+}
|
2020-11-06 00:04:57 +00:00
|
|
|
{$WARN 6058 off : Call to subroutine "$1" marked as inline is not inlined}
|
2020-11-22 18:49:28 +00:00
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
2020-10-24 22:07:31 +00:00
|
|
|
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, LCLVersion,
|
|
|
|
StdCtrls, Buttons, ExtCtrls, ComCtrls,
|
|
|
|
TASources, TAStyles, TASeries,
|
|
|
|
MainUnit, FunctionsLib, Globals, DataProcs, MatrixLib,
|
|
|
|
ReportFrameUnit, BasicStatsReportAndChartFormUnit;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
TABRAnovaData = record
|
|
|
|
// Counts
|
|
|
|
NoAGrps, NoBGrps, NInGrp, TotalN: Integer;
|
|
|
|
Acnt, Bcnt, Ccnt: IntDyneVec;
|
|
|
|
|
|
|
|
// Degrees of freedom
|
|
|
|
DFA, DFB, DFC, DFAB, DFAC, DFBC, DFABC, DFBetween: double;
|
|
|
|
DFerrorBetween, DFWithin, DFerrorWithin: double;
|
|
|
|
|
|
|
|
// Sums
|
|
|
|
ASums, BSums, CSums, SumPSqr: DblDyneVec;
|
|
|
|
ABSums, ACSums, BCSums: DblDyneMat;
|
|
|
|
ABCSums: DblDyneCube;
|
|
|
|
ABCNcnt: IntDyneCube;
|
|
|
|
GrandTotal: Double;
|
|
|
|
|
|
|
|
// Sums of squares
|
|
|
|
SSA, SSB, SSC, SSAB, SSAC, SSBC, SSABC: Double;
|
|
|
|
SSBetweenSubjects, SSWithinSubjects: Double;
|
|
|
|
SSerrorBetween, SSerrorWithin: Double;
|
|
|
|
SumXSqr: Double;
|
|
|
|
|
|
|
|
// Mean standard errors
|
|
|
|
MSA, MSB, MSC, MSAB, MSAC, MSBC, MSABC, MSerrorBetween, MSerrorWithin: Double;
|
|
|
|
|
|
|
|
// F values
|
|
|
|
FA, FB, FC, FAB, FAC, FBC, FABC: Double;
|
|
|
|
|
|
|
|
// Probabilities
|
|
|
|
ProbA, ProbB, ProbC, ProbAB, ProbAC, ProbBC, ProbABC: Double;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
{ TABRAnovaForm }
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
TABRAnovaForm = class(TBasicStatsReportAndChartForm)
|
2020-03-30 18:01:44 +00:00
|
|
|
AInBtn: TBitBtn;
|
|
|
|
AOutBtn: TBitBtn;
|
|
|
|
BInBtn: TBitBtn;
|
|
|
|
BOutBtn: TBitBtn;
|
2020-10-24 15:56:52 +00:00
|
|
|
ChartStyles: TChartStyles;
|
2020-10-24 22:07:31 +00:00
|
|
|
ThreeDChk: TCheckBox;
|
2020-03-30 18:01:44 +00:00
|
|
|
CInBtn: TBitBtn;
|
|
|
|
COutBtn: TBitBtn;
|
2020-10-24 15:56:52 +00:00
|
|
|
ACodesEdit: TEdit;
|
|
|
|
BCodesEdit: TEdit;
|
|
|
|
ListChartSource_AB: TListChartSource;
|
|
|
|
ListChartSource_AC: TListChartSource;
|
|
|
|
ListChartSource_BC: TListChartSource;
|
2020-10-24 22:07:31 +00:00
|
|
|
MeansPage: TTabSheet;
|
|
|
|
BoxTestsPage: TTabSheet;
|
2020-03-30 18:01:44 +00:00
|
|
|
TestChk: TCheckBox;
|
|
|
|
PlotChk: TCheckBox;
|
2020-10-24 15:56:52 +00:00
|
|
|
OptionsGroup: TGroupBox;
|
2020-03-30 18:01:44 +00:00
|
|
|
Label1: TLabel;
|
|
|
|
Label2: TLabel;
|
|
|
|
Label3: TLabel;
|
|
|
|
Label4: TLabel;
|
|
|
|
CList: TListBox;
|
|
|
|
VarList: TListBox;
|
2020-10-24 15:56:52 +00:00
|
|
|
procedure ACodesEditChange(Sender: TObject);
|
2020-03-30 18:01:44 +00:00
|
|
|
procedure AInBtnClick(Sender: TObject);
|
|
|
|
procedure AOutBtnClick(Sender: TObject);
|
|
|
|
procedure BInBtnClick(Sender: TObject);
|
|
|
|
procedure BOutBtnClick(Sender: TObject);
|
|
|
|
procedure CInBtnClick(Sender: TObject);
|
2020-10-24 15:56:52 +00:00
|
|
|
procedure CListDblClick(Sender: TObject);
|
2020-10-24 21:21:15 +00:00
|
|
|
procedure CListSelectionChange(Sender: TObject; {%H-}User: boolean);
|
2020-03-30 18:01:44 +00:00
|
|
|
procedure COutBtnClick(Sender: TObject);
|
2020-10-24 22:07:31 +00:00
|
|
|
procedure PlotChkChange(Sender: TObject);
|
|
|
|
procedure ThreeDChkChange(Sender: TObject);
|
2020-10-24 15:56:52 +00:00
|
|
|
procedure VarListDblClick(Sender: TObject);
|
2020-10-25 10:21:35 +00:00
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
private
|
2020-10-24 20:38:29 +00:00
|
|
|
type TInteraction = (AB, AC, BC);
|
|
|
|
|
|
|
|
private
|
2020-03-30 18:01:44 +00:00
|
|
|
ColNoSelected: IntDyneVec;
|
2020-10-25 10:21:35 +00:00
|
|
|
ACol, BCol, NoSelected, MinA, MaxA, MinB, MaxB: integer;
|
|
|
|
MaxRows, MaxCols: integer;
|
|
|
|
selected: Integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-24 22:07:31 +00:00
|
|
|
FMeansReportFrame: TReportFrame;
|
|
|
|
FBoxTestsReportFrame: TReportFrame;
|
2020-10-24 20:38:29 +00:00
|
|
|
FBtnAB, FBtnAC, FBtnBC: TToolButton;
|
2020-10-24 22:07:31 +00:00
|
|
|
FBarSeries: TBarSeries;
|
2020-10-24 20:38:29 +00:00
|
|
|
procedure InteractionChanged(Sender: TObject);
|
2020-10-25 10:21:35 +00:00
|
|
|
procedure Set3DPlot(AEnable: Boolean);
|
|
|
|
|
|
|
|
function InitData(out AData: TABRAnovaData): Boolean;
|
|
|
|
procedure GetData(var AData: TABRAnovaData);
|
|
|
|
procedure Calculate(var AData: TABRAnovaData);
|
|
|
|
procedure Summarize(const AData: TABRAnovaData; AReport: TStrings);
|
|
|
|
procedure MeansReport(const AData: TABRAnovaData; AReport: TStrings);
|
|
|
|
procedure BoxTests(const AData: TABRAnovaData; AReport: TStrings);
|
|
|
|
procedure PreparePlot(const AData: TABRAnovaData);
|
2020-10-24 20:38:29 +00:00
|
|
|
procedure PlotMeans(AInteraction: TInteraction);
|
2020-10-25 10:21:35 +00:00
|
|
|
procedure CleanUp(var AData: TABRAnovaData);
|
2020-10-24 15:56:52 +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-10-24 15:56:52 +00:00
|
|
|
constructor Create(AOwner: TComponent); override;
|
|
|
|
procedure Reset; override;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
var
|
2020-10-24 15:56:52 +00:00
|
|
|
ABRAnovaForm: TABRAnovaForm;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
implementation
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
{$R *.lfm}
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
uses
|
|
|
|
Math,
|
2020-10-24 22:07:31 +00:00
|
|
|
TAChartUtils, TALegend, TACustomSource, TACustomSeries,
|
2020-10-24 20:38:29 +00:00
|
|
|
Utils, MathUnit, GridProcs, ChartFrameUnit;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
{ TABRAnovaForm }
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
constructor TABRAnovaForm.Create(AOwner: TComponent);
|
2020-10-24 20:38:29 +00:00
|
|
|
var
|
|
|
|
btn: TToolButton;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 15:56:52 +00:00
|
|
|
inherited;
|
2020-10-24 20:38:29 +00:00
|
|
|
|
2020-10-24 22:07:31 +00:00
|
|
|
FMeansReportFrame := TReportFrame.Create(self);
|
|
|
|
FMeansReportFrame.Name := '';
|
|
|
|
FMeansReportFrame.Parent := MeansPage;
|
|
|
|
FMeansReportFrame.Align := alClient;
|
|
|
|
FMeansReportFrame.BorderSpacing.Left := 0;
|
|
|
|
FMeansReportFrame.BorderSpacing.Top := 0;
|
|
|
|
FMeansReportFrame.BorderSpacing.Bottom := 0;
|
|
|
|
FMeansReportFrame.BorderSpacing.Right := 0;
|
|
|
|
|
|
|
|
FBoxTestsReportFrame := TReportFrame.Create(self);
|
|
|
|
FBoxTestsReportFrame.Name := '';
|
|
|
|
FBoxTestsReportFrame.Parent := BoxTestsPage;
|
|
|
|
FBoxTestsReportFrame.Align := alClient;
|
|
|
|
FBoxTestsReportFrame.BorderSpacing.Left := 0;
|
|
|
|
FBoxTestsReportFrame.BorderSpacing.Top := 0;
|
|
|
|
FBoxTestsReportFrame.BorderSpacing.Bottom := 0;
|
|
|
|
FBoxTestsReportFrame.BorderSpacing.Right := 0;
|
|
|
|
|
2020-10-24 20:38:29 +00:00
|
|
|
FChartFrame.Chart.Margins.Bottom := 0;
|
|
|
|
FChartFrame.Chart.BottomAxis.AxisPen.Visible := true;
|
|
|
|
FChartFrame.Chart.BottomAxis.ZPosition := 1;
|
|
|
|
FChartFrame.Chart.BottomAxis.Grid.Visible := false;
|
|
|
|
|
|
|
|
FChartFrame.ChartToolbar.ShowCaptions := true;
|
|
|
|
FChartFrame.ChartToolbar.ButtonHeight := 40;;
|
|
|
|
|
|
|
|
btn := TToolButton.Create(FChartFrame.ChartToolbar);
|
|
|
|
btn.Style := tbsDivider;
|
|
|
|
AddButtonToToolbar(btn, FChartFrame.ChartToolbar);
|
|
|
|
|
|
|
|
FBtnAB := TToolButton.Create(FChartFrame.ChartToolbar);
|
|
|
|
FBtnAB.Caption := 'AB interaction';
|
|
|
|
FBtnAB.Down := true;
|
|
|
|
FBtnAB.Style := tbsCheck;
|
|
|
|
FBtnAB.Grouped := true;
|
|
|
|
FBtnAB.OnClick := @InteractionChanged;
|
|
|
|
AddButtonToToolbar(FBtnAB, FChartFrame.ChartToolbar);
|
|
|
|
|
|
|
|
FBtnAC := TToolButton.Create(FChartFrame.ChartToolbar);
|
|
|
|
FBtnAC.Caption := 'AC interaction';
|
|
|
|
FBtnAC.Grouped := true;
|
|
|
|
FBtnAC.Style := tbsCheck;
|
|
|
|
FBtnAC.OnClick := @InteractionChanged;
|
|
|
|
AddButtonToToolbar(FBtnAC, FChartFrame.ChartToolbar);
|
|
|
|
|
|
|
|
FBtnBC := TToolButton.Create(FChartFrame.ChartToolbar);
|
|
|
|
FbtnBC.Caption := 'BC interaction';
|
|
|
|
FBtnBC.Grouped := true;
|
|
|
|
FBtnBC.Style := tbsCheck;
|
|
|
|
FBtnBC.OnClick := @InteractionChanged;
|
|
|
|
AddButtonToToolbar(FBtnBC, FChartFrame.ChartToolbar);
|
|
|
|
|
|
|
|
PageControl.ActivePageIndex := 0;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
procedure TABRAnovaForm.AdjustConstraints;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 15:56:52 +00:00
|
|
|
inherited;
|
|
|
|
|
|
|
|
ParamsPanel.Constraints.MinWidth := Max(
|
|
|
|
4*CloseBtn.Width + 3*CloseBtn.BorderSpacing.Left,
|
|
|
|
OptionsGroup.Width
|
|
|
|
);
|
|
|
|
ParamsPanel.Constraints.MinHeight := COutBtn.Top + COutBtn.Height +
|
|
|
|
OptionsGroup.BorderSpacing.Top + OptionsGroup.Height +
|
|
|
|
ButtonBevel.Height + CloseBtn.BorderSpacing.Top + CloseBtn.Height
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
|
|
|
|
procedure TABRAnovaForm.ACodesEditChange(Sender: TObject);
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
|
|
|
|
procedure TABRAnovaForm.AInBtnClick(Sender: TObject);
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
|
|
|
index: integer;
|
|
|
|
begin
|
|
|
|
index := VarList.ItemIndex;
|
2020-10-24 15:56:52 +00:00
|
|
|
if (index > -1) and (ACodesEdit.Text = '') then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 15:56:52 +00:00
|
|
|
ACodesEdit.Text := VarList.Items[index];
|
2020-03-30 18:01:44 +00:00
|
|
|
VarList.Items.Delete(index);
|
|
|
|
end;
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
|
|
|
|
procedure TABRAnovaForm.AOutBtnClick(Sender: TObject);
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 15:56:52 +00:00
|
|
|
if ACodesEdit.Text <> '' then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 15:56:52 +00:00
|
|
|
VarList.Items.Add(ACodesEdit.Text);
|
|
|
|
ACodesEdit.Text := '';
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
|
|
|
|
procedure TABRAnovaForm.BInBtnClick(Sender: TObject);
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
|
|
|
index: integer;
|
|
|
|
begin
|
|
|
|
index := VarList.ItemIndex;
|
2020-10-24 15:56:52 +00:00
|
|
|
if (index > -1) and (BCodesEdit.Text = '') then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 15:56:52 +00:00
|
|
|
BCodesEdit.Text := VarList.Items[index];
|
2020-03-30 18:01:44 +00:00
|
|
|
VarList.Items.Delete(index);
|
|
|
|
end;
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
procedure TABRAnovaForm.BOutBtnClick(Sender: TObject);
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 15:56:52 +00:00
|
|
|
if BCodesEdit.Text <> '' then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 15:56:52 +00:00
|
|
|
VarList.Items.Add(BCodesEdit.Text);
|
|
|
|
BCodesEdit.Text := '';
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
|
|
|
|
procedure TABRAnovaForm.CInBtnClick(Sender: TObject);
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
|
|
|
i: integer;
|
|
|
|
begin
|
|
|
|
i := 0;
|
|
|
|
while i < VarList.Items.Count do
|
|
|
|
begin
|
|
|
|
if VarList.Selected[i] then
|
|
|
|
begin
|
|
|
|
CList.Items.Add(VarList.Items[i]);
|
|
|
|
VarList.Items.Delete(i);
|
|
|
|
i := 0;
|
|
|
|
end else
|
|
|
|
inc(i);
|
|
|
|
end;
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
procedure TABRAnovaForm.CleanUp(var AData: TABRAnovaData);
|
2020-10-24 15:56:52 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
with AData do
|
|
|
|
begin
|
|
|
|
ABCNcnt := nil;
|
|
|
|
ABCSums := nil;
|
|
|
|
Ccnt := nil;
|
|
|
|
Bcnt := nil;
|
|
|
|
Acnt := nil;
|
|
|
|
SumPSqr := nil;
|
|
|
|
//{
|
|
|
|
BCSums := nil; // needed for plotting
|
|
|
|
ACSums := nil;
|
|
|
|
ABSums := nil;
|
|
|
|
//}
|
|
|
|
CSums := nil;
|
|
|
|
BSums := nil;
|
|
|
|
ASums := nil;
|
|
|
|
ColNoSelected := nil;
|
|
|
|
end;
|
2020-10-24 15:56:52 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TABRAnovaForm.CListDblClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
index: Integer;
|
|
|
|
begin
|
|
|
|
index := CList.ItemIndex;
|
|
|
|
if index > -1 then
|
|
|
|
begin
|
|
|
|
VarList.Items.Add(CList.Items[index]);
|
|
|
|
CList.Items.Delete(index);
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TABRAnovaForm.CListSelectionChange(Sender: TObject; User: boolean);
|
|
|
|
begin
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TABRAnovaForm.Compute;
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
|
|
|
lReport: TStrings;
|
2020-10-24 20:38:29 +00:00
|
|
|
interaction: TInteraction;
|
2020-10-25 10:21:35 +00:00
|
|
|
data: TABRAnovaData;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
|
|
|
lReport := TStringList.Create;
|
|
|
|
try
|
2020-10-25 10:21:35 +00:00
|
|
|
if InitData(data) then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
GetData(data);
|
|
|
|
Calculate(data);
|
|
|
|
Summarize(data, lReport);
|
|
|
|
MeansReport(data, lReport);
|
2020-10-24 22:07:31 +00:00
|
|
|
|
2020-10-24 23:17:58 +00:00
|
|
|
BoxTestsPage.TabVisible := TestChk.Checked;
|
2020-10-24 20:38:29 +00:00
|
|
|
if TestChk.Checked then
|
2020-10-24 23:17:58 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
BoxTests(data, lReport);
|
2020-10-24 23:17:58 +00:00
|
|
|
//BoxTestsPage.PageIndex := 2;
|
|
|
|
end;
|
2020-10-24 20:38:29 +00:00
|
|
|
|
2020-10-24 23:17:58 +00:00
|
|
|
ChartPage.TabVisible := PlotChk.Checked;
|
2020-10-24 20:38:29 +00:00
|
|
|
if PlotChk.Checked then
|
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
PreparePlot(data);
|
2020-10-24 20:38:29 +00:00
|
|
|
if FBtnAB.Down then interaction := AB else
|
|
|
|
if FBtnAC.Down then interaction := AC else
|
|
|
|
if FBtnBC.Down then interaction := BC;
|
|
|
|
PlotMeans(interaction);
|
2020-10-24 23:17:58 +00:00
|
|
|
ChartPage.PageIndex := PageControl.PageCount-1;
|
2020-10-24 20:38:29 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
finally
|
|
|
|
lReport.Free;
|
2020-10-25 10:21:35 +00:00
|
|
|
CleanUp(data);
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
procedure TABRAnovaForm.COutBtnClick(Sender: TObject);
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
i := 0;
|
|
|
|
while i < CList.Items.Count do
|
|
|
|
begin
|
|
|
|
if CList.Selected[i] then
|
|
|
|
begin
|
|
|
|
VarList.Items.Add(CList.Items[i]);
|
|
|
|
CList.Items.Delete(i);
|
|
|
|
i := 0;
|
|
|
|
end else
|
|
|
|
inc(i);
|
|
|
|
end;
|
|
|
|
VarList.ItemIndex := -1;
|
|
|
|
CList.ItemIndex := -1;
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
|
2020-10-24 22:07:31 +00:00
|
|
|
procedure TABRAnovaForm.PlotChkChange(Sender: TObject);
|
|
|
|
begin
|
|
|
|
ThreeDChk.Enabled := PlotChk.Checked;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
function TABRAnovaForm.InitData(out AData: TABRAnovaData): Boolean;
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-10-25 10:21:35 +00:00
|
|
|
cellStr: string;
|
|
|
|
groupVal: Integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
i, j, k: integer;
|
|
|
|
begin
|
|
|
|
Result := false;
|
|
|
|
|
2020-10-24 21:21:15 +00:00
|
|
|
SetLength(ColNoSelected, NoVariables);
|
|
|
|
ACol := GetVariableIndex(OS3MainFrm.DataGrid, ACodesEdit.Text);
|
|
|
|
BCol := GetVariableIndex(OS3MainFrm.DataGrid, BCodesEdit.Text);
|
|
|
|
if ((ACol = -1) or (BCol = -1)) then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 21:21:15 +00:00
|
|
|
// This case should already have been caught, but anyway...
|
|
|
|
ErrorMsg('Select a variable for the A and B Variable Codes.');
|
2020-03-30 18:01:44 +00:00
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
NoSelected := CList.Items.Count;
|
2020-10-25 10:21:35 +00:00
|
|
|
MinA := MaxInt;
|
|
|
|
MaxA := -MaxInt;
|
|
|
|
MinB := MaxInt;
|
|
|
|
MaxB := -MaxInt;
|
2020-03-30 18:01:44 +00:00
|
|
|
for i := 1 to NoCases do
|
|
|
|
begin
|
2020-10-24 15:56:52 +00:00
|
|
|
if not ValidValue(OS3MainFrm.DataGrid, i, ACol) then continue;
|
2020-10-25 10:21:35 +00:00
|
|
|
cellStr := Trim(OS3MainFrm.DataGrid.Cells[ACol, i]);
|
|
|
|
groupVal := round(StrToFloat(cellstr));
|
|
|
|
if (groupVal > MaxA) then MaxA := groupVal;
|
|
|
|
if (groupVal < MinA) then MinA := groupVal;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
cellStr := Trim(OS3MainFrm.DataGrid.Cells[BCol, i]);
|
2020-10-24 15:56:52 +00:00
|
|
|
if not ValidValue(OS3MainFrm.DataGrid, i, BCol) then continue;
|
2020-10-25 10:21:35 +00:00
|
|
|
groupVal := round(StrToFLoat(cellStr));
|
|
|
|
if (groupVal > MaxB) then MaxB := groupVal;
|
|
|
|
if (groupVal < MinB) then MinB := groupVal;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-10-25 10:21:35 +00:00
|
|
|
|
|
|
|
with AData do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
NoAGrps := MaxA - MinA + 1;
|
|
|
|
NoBGrps := MaxB - MinB + 1;
|
|
|
|
MaxRows := NoAGrps * NoBGrps;
|
|
|
|
MaxCols := NoSelected;
|
|
|
|
if (NoBGrps > NoSelected) then MaxCols := NoBGrps;
|
|
|
|
if (MaxCols > MaxRows) then MaxRows := MaxCols;
|
|
|
|
|
|
|
|
// allocate storage for arrays
|
|
|
|
SetLength(ASums, NoAGrps);
|
|
|
|
SetLength(Bsums, NoBGrps);
|
|
|
|
SetLength(Csums, NoCases);
|
|
|
|
SetLength(ABSums, NoAGrps, NoBGrps);
|
|
|
|
SetLength(ACSums, NoAGrps, NoSelected);
|
|
|
|
SetLength(BCSums, NoBGrps, NoSelected);
|
|
|
|
SetLength(SumPSqr, NoCases);
|
|
|
|
SetLength(Acnt, NoAGrps);
|
|
|
|
SetLength(Bcnt, NoBGrps);
|
|
|
|
SetLength(Ccnt, MaxRows);
|
|
|
|
SetLength(ABCSums, NoAGrps, NoBGrps, NoSelected);
|
|
|
|
SetLength(ABCNcnt, NoAGrps, NoBGrps, NoSelected);
|
|
|
|
|
|
|
|
// initialize arrays
|
|
|
|
for i := 0 to NoAGrps-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
ASums[i] := 0.0;
|
|
|
|
Acnt[i] := 0;
|
|
|
|
for j := 0 to NoBGrps-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
ABSums[i, j] := 0.0;
|
|
|
|
for k := 0 to NoSelected-1 do
|
|
|
|
begin
|
|
|
|
ABCSums[i, j, k] := 0.0;
|
|
|
|
ABCNcnt[i, j, k] := 0;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
for j := 0 to NoSelected-1 do
|
|
|
|
begin
|
|
|
|
ACSums[i, j] := 0.0;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
end;
|
2020-10-25 10:21:35 +00:00
|
|
|
for i := 0 to NoBGrps-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
BSums[i] := 0.0;
|
|
|
|
Bcnt[i] := 0;
|
|
|
|
for j := 0 to NoSelected-1 do
|
|
|
|
begin
|
|
|
|
BCSums[i, j] := 0.0;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-10-25 10:21:35 +00:00
|
|
|
for i := 0 to NoSelected-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
CSums[i] := 0.0;
|
|
|
|
Ccnt[i] := 0;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-10-25 10:21:35 +00:00
|
|
|
for i := 0 to NoCases-1 do
|
|
|
|
SumPSqr[i] := 0.0;
|
|
|
|
GrandTotal := 0.0;
|
|
|
|
TotalN := 0;
|
|
|
|
SumXSqr := 0.0;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
Result := true;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 20:38:29 +00:00
|
|
|
procedure TABRAnovaForm.InteractionChanged(Sender: TObject);
|
|
|
|
var
|
|
|
|
interaction: TInteraction;
|
|
|
|
begin
|
|
|
|
if TObject(Sender) is TToolButton then
|
|
|
|
TToolButton(Sender).Down := true;
|
|
|
|
|
2020-10-24 21:21:15 +00:00
|
|
|
if not PlotChk.Checked then
|
|
|
|
exit;
|
|
|
|
|
2020-10-24 20:38:29 +00:00
|
|
|
if FBtnAB.Down then
|
|
|
|
interaction := AB
|
|
|
|
else if FBtnAC.Down then
|
|
|
|
interaction := AC
|
|
|
|
else if FBtnBC.Down then
|
|
|
|
interaction := BC;
|
|
|
|
|
|
|
|
PlotMeans(interaction);
|
2020-10-24 21:21:15 +00:00
|
|
|
UpdateBtnStates;
|
2020-10-24 20:38:29 +00:00
|
|
|
end;
|
|
|
|
|
2020-10-24 21:21:15 +00:00
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
procedure TABRAnovaForm.GetData(var AData: TABRAnovaData);
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
|
|
|
i, j, SubjA, SubjB: integer;
|
|
|
|
X: double;
|
2020-10-25 10:21:35 +00:00
|
|
|
subjTot: Double;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
|
|
|
for i := 0 to NoSelected - 1 do
|
2020-10-24 15:56:52 +00:00
|
|
|
ColNoSelected[i] := GetVariableIndex(OS3MainFrm.DataGrid, CList.Items[i]);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
ColNoSelected[NoSelected] := ACol;
|
2020-10-24 15:56:52 +00:00
|
|
|
ColNoSelected[NoSelected+1] := BCol; // must be over-dimensioned by +2
|
2020-03-30 18:01:44 +00:00
|
|
|
selected := NoSelected + 2;
|
|
|
|
|
|
|
|
// read data and store sums
|
2020-10-25 10:21:35 +00:00
|
|
|
with AData do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
for i := 1 to NoCases do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
if not DataProcs.GoodRecord(i,selected,ColNoSelected) then continue;
|
|
|
|
SubjA := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ACol,i])));
|
|
|
|
SubjA := SubjA - MinA + 1;
|
|
|
|
SubjB := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[BCol,i])));
|
|
|
|
SubjB := SubjB - MinB + 1;
|
|
|
|
SubjTot := 0.0;
|
|
|
|
for j := 0 to NoSelected-1 do
|
|
|
|
begin
|
|
|
|
X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[j], i]));
|
|
|
|
SubjTot := SubjTot + X;
|
|
|
|
SumXSqr := SumXSqr + (X * X);
|
|
|
|
ABCSums[SubjA-1, SubjB-1, j] := ABCSums[SubjA-1, SubjB-1, j] + X;
|
|
|
|
ABCNcnt[SubjA-1, SubjB-1, j] := ABCNcnt[SubjA-1, SubjB-1, j] + 1;
|
|
|
|
Acnt[SubjA-1] := Acnt[SubjA-1] + 1;
|
|
|
|
Bcnt[SubjB-1] := Bcnt[SubjB-1] + 1;
|
|
|
|
Ccnt[j] := Ccnt[j] + 1;
|
|
|
|
TotalN := TotalN + 1;
|
|
|
|
end;
|
|
|
|
SumPSqr[i-1] := SumPSqr[i-1] + (SubjTot * SubjTot);
|
|
|
|
GrandTotal := GrandTotal + SubjTot;
|
|
|
|
NinGrp := ABCNcnt[0,0,0];
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
procedure TABRAnovaForm.Calculate(var AData: TABRAnovaData);
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-10-24 21:21:15 +00:00
|
|
|
SumA, SumB, SumC, SumAB, SumAC, SumBC, SumABC : double;
|
|
|
|
Term1, Term2, Term3, Term4, Term5, Term6, Term7, Term8, Term9, Term10 : double;
|
|
|
|
i, j, k, CountA, CountB, CountC: integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
with AData do
|
2020-10-24 21:21:15 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
Term1 := (GrandTotal * GrandTotal) / TotalN;
|
|
|
|
Term2 := SumXSqr;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
Term3 := 0.0;
|
|
|
|
countA := 0;
|
2020-10-24 21:21:15 +00:00
|
|
|
for i := 0 to NoAGrps-1 do
|
2020-10-25 10:21:35 +00:00
|
|
|
begin
|
|
|
|
SumA := 0.0;
|
|
|
|
countA := countA + Acnt[i];
|
|
|
|
for j := 0 to NoBGrps-1 do
|
|
|
|
for k := 0 to NoSelected-1 do SumA := SumA + ABCSums[i, j, k];
|
|
|
|
ASums[i] := ASums[i] + SumA;
|
|
|
|
Term3 := Term3 + sqr(SumA);
|
|
|
|
end;
|
|
|
|
Term3 := Term3 / (NInGrp * NoBGrps * NoSelected);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
Term4 := 0;
|
|
|
|
countB := 0;
|
2020-10-24 21:21:15 +00:00
|
|
|
for j := 0 to NoBGrps-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
SumB := 0.0;
|
|
|
|
CountB := CountB + Bcnt[j];
|
|
|
|
for i := 0 to NoAGrps-1 do
|
|
|
|
for k := 0 to NoSelected-1 do SumB := SumB + ABCSums[i, j, k];
|
|
|
|
BSums[j] := BSums[j] + SumB;
|
|
|
|
Term4 := Term4 + sqr(SumB);
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-10-25 10:21:35 +00:00
|
|
|
Term4 := Term4 / (NInGrp * NoAGrps * NoSelected);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
Term5 := 0.0;
|
|
|
|
countC := 0;
|
2020-10-24 21:21:15 +00:00
|
|
|
for k := 0 to NoSelected-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
SumC := 0.0;
|
|
|
|
CountC := CountC + Ccnt[k];
|
|
|
|
for i := 0 to NoAGrps-1 do
|
|
|
|
for j := 0 to NoBGrps-1 do SumC := SumC + ABCSums[i, j, k];
|
|
|
|
CSums[k] := CSums[k] + SumC;
|
|
|
|
Term5 := Term5 + sqr(SumC);
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-10-25 10:21:35 +00:00
|
|
|
Term5 := Term5 / (NInGrp * NoAGrps * NoBGrps);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
Term6 := 0.0;
|
|
|
|
for i := 0 to NoAGrps-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
for j := 0 to NoBGrps-1 do
|
|
|
|
begin
|
|
|
|
SumAB := 0.0;
|
|
|
|
//CountAB := CountAB + ABcnt^[i,j];
|
|
|
|
for k := 0 to NoSelected-1 do SumAB := SumAB + ABCSums[i, j, k];
|
|
|
|
ABSums[i, j] := ABSums[i, j] + SumAB;
|
|
|
|
Term6 := Term6 + sqr(SumAB);
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-10-25 10:21:35 +00:00
|
|
|
Term6 := Term6 / (NInGrp * NoSelected);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
Term7 := 0.0;
|
|
|
|
for i := 0 to NoAGrps-1 do
|
|
|
|
begin
|
|
|
|
for k := 0 to NoSelected-1 do
|
|
|
|
begin
|
|
|
|
SumAC := 0.0;
|
|
|
|
for j := 0 to NoBGrps-1 do SumAC := SumAC + ABCSums[i, j, k];
|
|
|
|
ACSums[i, k] := ACSums[i, k] + SumAC;
|
|
|
|
Term7 := Term7 + sqr(SumAC);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
Term7 := Term7 / (NInGrp * NoBGrps);
|
|
|
|
|
|
|
|
Term8 := 0.0;
|
2020-10-24 21:21:15 +00:00
|
|
|
for j := 0 to NoBGrps-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 21:21:15 +00:00
|
|
|
for k := 0 to NoSelected-1 do
|
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
SumBC := 0.0;
|
|
|
|
for i := 0 to NoAGrps-1 do SumBC := SumBC + ABCSums[i, j, k];
|
|
|
|
BCSums[j, k] := BCSums[j, k] + SumBC;
|
|
|
|
Term8 := Term8 + sqr(SumBC);
|
2020-10-24 21:21:15 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-10-25 10:21:35 +00:00
|
|
|
Term8 := Term8 / (NInGrp * NoAGrps);
|
|
|
|
|
|
|
|
Term9 := 0.0;
|
|
|
|
for i := 0 to NoAGrps-1 do
|
|
|
|
begin
|
|
|
|
for j := 0 to NoBGrps-1 do
|
|
|
|
begin
|
|
|
|
for k := 0 to NoSelected-1 do
|
|
|
|
begin
|
|
|
|
SumABC := ABCSums[i, j, k];
|
|
|
|
//CountABC := CountABC + ABCNcnt[i,j,k];
|
|
|
|
Term9 := Term9 + sqr(SumABC);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
Term9 := Term9 / NInGrp;
|
|
|
|
|
|
|
|
Term10 := 0.0;
|
|
|
|
for i := 0 to NoCases-1 do Term10 := Term10 + SumPSqr[i];
|
|
|
|
Term10 := Term10 / NoSelected;
|
|
|
|
|
|
|
|
//Get DF, SS, MS, F and Probabilities
|
|
|
|
DFBetween := (NInGrp * NoAGrps * NoBGrps) - 1.0;
|
|
|
|
DFA := NoAGrps - 1.0;
|
|
|
|
DFB := NoBGrps - 1.0;
|
|
|
|
DFAB := (NoAGrps - 1.0) * (NoBGrps - 1.0);
|
|
|
|
DFerrorBetween := (NoAGrps * NoBGrps) * (NInGrp - 1.0);
|
|
|
|
DFWithin := (NInGrp * NoAGrps * NoBGrps) * (NoSelected - 1.0);
|
|
|
|
DFC := NoSelected - 1.0;
|
|
|
|
DFAC := (NoAGrps - 1.0) * (NoSelected - 1.0);
|
|
|
|
DFBC := (NoBGrps - 1.0) * (NoSelected - 1.0);
|
|
|
|
DFABC := (NoAGrps - 1.0) * (NoBGrps - 1.0) * (NoSelected - 1.0);
|
|
|
|
DFerrorWithin := NoAGrps * NoBGrps * (NInGrp - 1.0) * (NoSelected - 1.0);
|
|
|
|
|
|
|
|
SSBetweenSubjects := Term10 - Term1;
|
|
|
|
SSA := Term3 - Term1;
|
|
|
|
SSB := Term4 - Term1;
|
|
|
|
SSAB := Term6 - Term3 - Term4 + Term1;
|
|
|
|
SSerrorBetween := Term10 - Term6;
|
|
|
|
SSWithinSubjects := Term2 - Term10;
|
|
|
|
SSC := Term5 - Term1;
|
|
|
|
SSAC := Term7 - Term3 - Term5 + Term1;
|
|
|
|
SSBC := Term8 - Term4 - Term5 + Term1;
|
|
|
|
SSABC := Term9 - Term6 - Term7 - Term8 + Term3 + Term4 + Term5 - Term1;
|
|
|
|
SSerrorWithin := Term2 - Term9 - Term10 + Term6;
|
|
|
|
|
|
|
|
MSA := SSA / DFA;
|
|
|
|
MSB := SSB / DFB;
|
|
|
|
MSAB := SSAB / DFAB;
|
|
|
|
MSerrorBetween := SSerrorBetween / DFerrorBetween;
|
|
|
|
MSC := SSC / DFC;
|
|
|
|
MSAC := SSAC / DFAC;
|
|
|
|
MSBC := SSBC / DFBC;
|
|
|
|
MSABC := SSABC / DFABC;
|
|
|
|
MSerrorWithin := SSerrorWithin / DFerrorWithin;
|
|
|
|
|
|
|
|
FA := MSA / MSerrorBetween;
|
|
|
|
FB := MSB / MSerrorBetween;
|
|
|
|
FAB := MSAB / MSerrorBetween;
|
|
|
|
FC := MSC / MSerrorWithin;
|
|
|
|
FAC := MSAC / MSerrorWithin;
|
|
|
|
FBC := MSBC / MSerrorWithin;
|
|
|
|
FABC := MSABC / MSerrorWithin;
|
|
|
|
|
|
|
|
ProbA := ProbF(FA, DFA, DFerrorBetween);
|
|
|
|
ProbB := ProbF(FB, DFB, DFerrorBetween);
|
|
|
|
ProbAB := ProbF(FAB, DFAB, DFerrorBetween);
|
|
|
|
ProbC := ProbF(FC, DFC, DFerrorWithin);
|
|
|
|
ProbAC := ProbF(FAC, DFAC, DFerrorWithin);
|
|
|
|
ProbBC := ProbF(FBC, DFBC, DFerrorWithin);
|
|
|
|
ProbABC := ProbF(FABC, DFABC, DFerrorWithin);
|
2020-10-24 21:21:15 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
procedure TABRAnovaForm.Summarize(const AData: TABRAnovaData; AReport: TStrings);
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
with AData do
|
|
|
|
begin
|
2020-10-25 17:45:52 +00:00
|
|
|
AReport.Add(DIVIDER_AUTO);
|
|
|
|
AReport.Add('SOURCE DF SS MS F PROB.');
|
2020-10-25 10:21:35 +00:00
|
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
2020-10-25 17:45:52 +00:00
|
|
|
AReport.Add('Between Subjects %5.0f%14.3f', [DFBetween, SSBetweenSubjects]);
|
|
|
|
AReport.Add(' A Effects %5.0f%14.3f%12.3f%10.3f%10.3f', [DFA, SSA, MSA, FA, ProbA]);
|
|
|
|
AReport.Add(' B Effects %5.0f%14.3f%12.3f%10.3f%10.3f', [DFB, SSB, MSB, FB, ProbB]);
|
|
|
|
AReport.Add(' AB Effects %5.0f%14.3f%12.3f%10.3f%10.3f', [DFAB, SSAB, MSAB, FAB, ProbAB]);
|
|
|
|
AReport.Add(' Error Between %5.0f%14.3f%12.3f', [DFerrorBetween, SSerrorBetween, MSerrorBetween]);
|
2020-10-25 10:21:35 +00:00
|
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
2020-10-25 17:45:52 +00:00
|
|
|
AReport.Add('Within Subjects %5.0f%14.3f', [DFWithin, SSWithinSubjects]);
|
|
|
|
AReport.Add(' C Replications %5.0f%14.3f%12.3f%10.3f%10.3f', [DFC, SSC, MSC, FC, ProbC]);
|
|
|
|
AReport.Add(' AC Effects %5.0f%14.3f%12.3f%10.3f%10.3f', [DFAC, SSAC, MSAC, FAC, ProbAC]);
|
|
|
|
AReport.Add(' BC Effects %5.0f%14.3f%12.3f%10.3f%10.3f', [DFBC, SSBC, MSBC, FBC, ProbBC]);
|
|
|
|
AReport.Add(' ABC Effects %5.0f%14.3f%12.3f%10.3f%10.3f', [DFABC, SSABC, MSABC, FABC, ProbABC]);
|
|
|
|
AReport.Add(' Error Within %5.0f%14.3f%12.3f', [DFerrorWithin, SSerrorWithin, MSerrorWithin]);
|
2020-10-25 10:21:35 +00:00
|
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
2020-10-25 17:45:52 +00:00
|
|
|
AReport.Add('Total %5.0f%14.3f', [DFBetween + DFWithin, SSBetweenSubjects + SSWithinSubjects]);
|
|
|
|
AReport.Add(DIVIDER_AUTO);
|
2020-10-25 10:21:35 +00:00
|
|
|
end;
|
2020-10-24 22:07:31 +00:00
|
|
|
|
|
|
|
FReportFrame.DisplayReport(AReport);
|
|
|
|
AReport.Clear;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-10-24 22:07:31 +00:00
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
procedure TABRAnovaForm.MeansReport(const AData: TABRAnovaData; AReport: TStrings);
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-10-24 22:55:18 +00:00
|
|
|
ColLabels: StrDyneVec = nil;
|
|
|
|
RowLabels: StrDyneVec = nil;
|
2020-10-24 23:17:58 +00:00
|
|
|
AMatrix: DblDyneMat = nil;
|
2020-10-26 18:00:52 +00:00
|
|
|
{%H-}ColHeader: string;
|
2020-03-30 18:01:44 +00:00
|
|
|
Title: string;
|
|
|
|
i, j, k, row: integer;
|
|
|
|
begin
|
2020-10-24 22:07:31 +00:00
|
|
|
AReport.Clear;
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
Title := 'ABR Means Table';
|
|
|
|
ColHeader := 'Repeated Measures';
|
2020-10-24 23:17:58 +00:00
|
|
|
SetLength(AMatrix, MaxRows, NoSelected);
|
2020-10-24 22:55:18 +00:00
|
|
|
SetLength(RowLabels, MaxRows);
|
|
|
|
SetLength(ColLabels, NoSelected);
|
|
|
|
row := 0;
|
2020-10-25 10:21:35 +00:00
|
|
|
for i := 0 to AData.NoAGrps-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
for j := 0 to AData.NoBGrps-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 22:55:18 +00:00
|
|
|
RowLabels[row] := Format('A%d B%d',[i+1, j+1]);
|
|
|
|
for k := 0 to NoSelected-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
AMatrix[row, k] := AData.ABCSums[i, j, k] / AData.NInGrp;
|
2020-10-24 22:55:18 +00:00
|
|
|
ColLabels[k] := OS3MainFrm.DataGrid.Cells[ColNoSelected[k], 0];
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
inc(row);
|
|
|
|
end;
|
|
|
|
end;
|
2020-10-25 10:21:35 +00:00
|
|
|
MatPrint(AMatrix, MaxRows, NoSelected, Title, RowLabels, ColLabels, AData.NInGrp, AReport);
|
2020-10-24 22:55:18 +00:00
|
|
|
|
|
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
|
|
AReport.Add('');
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
Title := 'AB Means Table';
|
|
|
|
ColHeader := 'B Levels';
|
2020-10-25 10:21:35 +00:00
|
|
|
SetLength(AMatrix, AData.NoAGrps, AData.NoBGrps);
|
|
|
|
SetLength(RowLabels, AData.NoAGrps);
|
|
|
|
SetLength(ColLabels, AData.NoBGrps);
|
|
|
|
for i := 0 to AData.NoAGrps-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 22:55:18 +00:00
|
|
|
RowLabels[i] := Format('A%d',[i+1]);
|
2020-10-25 10:21:35 +00:00
|
|
|
for j := 0 to AData.NoBGrps-1 do
|
|
|
|
AMatrix[i, j] := AData.ABSums[i, j] / (AData.NInGrp * NoSelected);
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-10-25 10:21:35 +00:00
|
|
|
for j := 0 to AData.NoBGrps-1 do
|
2020-10-24 22:55:18 +00:00
|
|
|
ColLabels[j] := Format('B %d',[j+1]);
|
2020-10-25 10:21:35 +00:00
|
|
|
MatPrint(AMatrix, AData.NoAgrps, AData.NoBgrps, Title, RowLabels, ColLabels, AData.NinGrp*NoSelected, AReport);
|
2020-10-24 22:55:18 +00:00
|
|
|
|
|
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
|
|
AReport.Add('');
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
Title := 'AC Means Table';
|
|
|
|
ColHeader := 'C Levels';
|
2020-10-25 10:21:35 +00:00
|
|
|
SetLength(AMatrix, AData.NoAGrps, NoSelected);
|
|
|
|
SetLength(RowLabels, AData.NoAGrps);
|
2020-10-24 22:55:18 +00:00
|
|
|
SetLength(ColLabels, NoSelected);
|
2020-10-25 10:21:35 +00:00
|
|
|
for i := 0 to AData.NoAGrps-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 22:55:18 +00:00
|
|
|
RowLabels[i] := Format('A%d',[i+1]);
|
|
|
|
for j := 0 to NoSelected-1 do
|
2020-10-25 10:21:35 +00:00
|
|
|
AMatrix[i, j] := AData.ACSums[i, j] / (AData.NInGrp * AData.NoBGrps);
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-10-24 22:55:18 +00:00
|
|
|
for j := 0 to NoSelected-1 do
|
|
|
|
ColLabels[j] := Format('C%d',[j+1]);
|
2020-10-25 10:21:35 +00:00
|
|
|
MatPrint(AMatrix, AData.NoAGrps, NoSelected, Title, RowLabels, ColLabels, AData.NInGrp*AData.NoBGrps, AReport);
|
2020-10-24 22:55:18 +00:00
|
|
|
|
|
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
|
|
AReport.Add('');
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
Title := 'BC Means Table';
|
|
|
|
ColHeader := 'C Levels';
|
2020-10-25 10:21:35 +00:00
|
|
|
SetLength(AMatrix, AData.NoBGrps, NoSelected);
|
|
|
|
SetLength(RowLabels, AData.NoBGrps);
|
2020-10-24 22:55:18 +00:00
|
|
|
SetLength(ColLabels, NoSelected);
|
2020-10-25 10:21:35 +00:00
|
|
|
for i := 0 to AData.NoBGrps-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 22:55:18 +00:00
|
|
|
RowLabels[i] := Format('B%d',[i+1]);
|
|
|
|
for j := 0 to NoSelected-1 do
|
2020-10-25 10:21:35 +00:00
|
|
|
AMatrix[i, j] := AData.BCSums[i, j] / (AData.NInGrp * AData.NoAGrps);
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-10-24 22:55:18 +00:00
|
|
|
for j := 0 to NoSelected-1 do
|
|
|
|
ColLabels[j] := Format('C%d', [j+1]);
|
2020-10-25 10:21:35 +00:00
|
|
|
MatPrint(AMatrix, AData.NoBGrps, NoSelected, Title, RowLabels, ColLabels, AData.NInGrp*AData.NoAGrps, AReport);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-24 22:07:31 +00:00
|
|
|
FMeansReportFrame.DisplayReport(AReport);
|
|
|
|
AReport.Clear;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
procedure TABRAnovaForm.BoxTests(const AData: TABRAnovaData; AReport: TStrings);
|
2020-03-30 18:01:44 +00:00
|
|
|
const
|
|
|
|
EPS = 1E-35;
|
|
|
|
var
|
2020-10-25 17:45:52 +00:00
|
|
|
errorcode: Boolean = false; // to silence the compiler
|
2020-10-24 21:21:15 +00:00
|
|
|
XVector: DblDyneVec = nil;
|
|
|
|
XSums: DblDyneVec = nil;
|
|
|
|
DetMat: DblDyneMat = nil;
|
2020-10-24 22:55:18 +00:00
|
|
|
ColLabels: StrDyneVec = nil;
|
|
|
|
RowLabels: StrDyneVec = nil;
|
2020-10-24 23:17:58 +00:00
|
|
|
AMatrix: DblDyneMat = nil;
|
|
|
|
PooledMat: DblDyneMat = nil;
|
2020-10-24 22:55:18 +00:00
|
|
|
M1, M2, Sum1, C1, C2, f1, f2, chi, ProbChi, X, avgvar, avgcov: double;
|
2020-10-26 18:00:52 +00:00
|
|
|
{%H-}ColHeader, LabelStr: string;
|
2020-10-24 22:55:18 +00:00
|
|
|
Title: string;
|
2020-03-30 18:01:44 +00:00
|
|
|
i, j, k, l, row, SubjA, SubjB, N, p, quad : integer;
|
|
|
|
Det: Double = 0.0;
|
|
|
|
begin
|
2020-10-24 22:07:31 +00:00
|
|
|
AReport.Clear;
|
|
|
|
|
2020-10-24 21:21:15 +00:00
|
|
|
SetLength(XVector, NoSelected);
|
|
|
|
SetLength(XSums, NoSelected);
|
|
|
|
SetLength(DetMat, NoSelected+1, NoSelected+1);
|
2020-10-24 22:55:18 +00:00
|
|
|
SetLength(ColLabels, NoSelected);
|
|
|
|
SetLength(RowLabels, NoSelected);
|
2020-10-24 23:17:58 +00:00
|
|
|
SetLength(AMatrix, NoSelected, NoSelected);
|
|
|
|
SetLength(PooledMat, NoSelected, NoSelected);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-24 21:21:15 +00:00
|
|
|
for i := 0 to NoSelected-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 22:55:18 +00:00
|
|
|
RowLabels[i] := Format('C%d', [i+1]);
|
|
|
|
ColLabels[i] := RowLabels[i];
|
2020-10-24 21:21:15 +00:00
|
|
|
for j := 0 to NoSelected-1 do PooledMat[i, j] := 0.0;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
// get variance-covariance AMatrix for the repeated measures within
|
|
|
|
// each combination of A and B levels. Pool them for the pooled
|
|
|
|
// covariance AMatrix. Get Determinants of each AMatrix.
|
|
|
|
//OutputFrm.Clear;
|
|
|
|
Sum1 := 0.0;
|
2020-10-25 10:21:35 +00:00
|
|
|
for i := 1 to AData.NoAGrps do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
for j := 1 to AData.NoBGrps do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 22:55:18 +00:00
|
|
|
LabelStr := Format('Variance-Covariance AMatrix for A%d B%d', [i,j]);
|
2020-03-30 18:01:44 +00:00
|
|
|
Title := LabelStr;
|
|
|
|
ColHeader := 'C Levels';
|
|
|
|
|
|
|
|
// initialize AMatrix for this combination
|
2020-10-24 21:21:15 +00:00
|
|
|
for k := 0 to NoSelected-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 21:21:15 +00:00
|
|
|
for L := 0 to NoSelected-1 do AMatrix[k,0] := 0.0;
|
|
|
|
XSums[k] := 0.0;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
// read data and add to covariances
|
|
|
|
for row := 1 to NoCases do
|
|
|
|
begin
|
2020-10-24 15:56:52 +00:00
|
|
|
if not DataProcs.GoodRecord(row, selected, ColNoSelected) then
|
2020-03-30 18:01:44 +00:00
|
|
|
continue;
|
2020-10-24 15:56:52 +00:00
|
|
|
SubjA := round(StrToFLoat(Trim(OS3MainFrm.DataGrid.Cells[ACol, row])));
|
2020-03-30 18:01:44 +00:00
|
|
|
SubjA := SubjA - MinA + 1;
|
2020-10-24 15:56:52 +00:00
|
|
|
SubjB := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[BCol, row])));
|
2020-03-30 18:01:44 +00:00
|
|
|
SubjB := SubjB - MinB + 1;
|
|
|
|
if ((SubjA <> i)or(SubjB <> j)) then
|
|
|
|
continue;
|
2020-10-24 21:21:15 +00:00
|
|
|
for k := 0 to NoSelected-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 21:21:15 +00:00
|
|
|
X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[k], row]));
|
|
|
|
XVector[k] := X;
|
|
|
|
XSums[k] := XSums[k] + X;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-10-24 21:21:15 +00:00
|
|
|
for k := 0 to NoSelected-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 21:21:15 +00:00
|
|
|
for L := 0 to NoSelected-1 do
|
|
|
|
AMatrix[k, L] := AMatrix[k, L] + (XVector[k] * XVector[L]);
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
end; // next case
|
|
|
|
|
|
|
|
// convert sums of cross-products to variance-covariance
|
2020-10-24 21:21:15 +00:00
|
|
|
for k := 0 to NoSelected-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 21:21:15 +00:00
|
|
|
for L := 0 to NoSelected-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
AMatrix[k, L] := AMatrix[k, L] - (XSums[k]*XSums[L] / AData.NInGrp);
|
|
|
|
AMatrix[k, L] := AMatrix[k, L] / (AData.NInGrp - 1);
|
2020-10-24 21:21:15 +00:00
|
|
|
PooledMat[k, L] := PooledMat[k, L] + AMatrix[k, L];
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 22:55:18 +00:00
|
|
|
MatPrint(AMatrix, NoSelected, NoSelected, Title, RowLabels, ColLabels, NoCases, AReport);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-24 23:17:58 +00:00
|
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
|
|
AReport.Add('');
|
|
|
|
|
2020-10-24 21:21:15 +00:00
|
|
|
for k := 0 to NoSelected-1 do
|
|
|
|
for L := 0 to NoSelected-1 do
|
|
|
|
DetMat[k, L] := AMatrix[k, L];
|
2020-10-24 23:17:58 +00:00
|
|
|
Determ(DetMat, NoSelected, NoSelected, Det, errorcode);
|
2020-03-30 18:01:44 +00:00
|
|
|
// if (Det > 0.0e35) then // wp: What's this???
|
|
|
|
if Det > EPS then
|
2020-10-25 10:21:35 +00:00
|
|
|
Sum1 := sum1 + (AData.NInGrp * ln(Det))
|
2020-03-30 18:01:44 +00:00
|
|
|
else
|
|
|
|
MessageDlg('Determinant of a covariance AMatrix <= 0.', mtWarning, [mbOK], 0);
|
|
|
|
end;// next B level
|
|
|
|
end; // next A level
|
|
|
|
|
2020-10-24 23:17:58 +00:00
|
|
|
// Get pooled variance-covariance
|
2020-10-24 21:21:15 +00:00
|
|
|
for i := 0 to NoSelected-1 do
|
|
|
|
for j := 0 to NoSelected-1 do
|
2020-10-25 10:21:35 +00:00
|
|
|
PooledMat[i, j] := PooledMat[i, j] / (AData.NoAGrps * AData.NoBGrps);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
Title := 'Pooled Variance-Covariance AMatrix';
|
2020-10-24 21:21:15 +00:00
|
|
|
MatPrint(PooledMat, NoSelected, NoSelected, Title, RowLabels, ColLabels, NoCases, AReport);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-24 23:17:58 +00:00
|
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
|
|
AReport.Add('');
|
|
|
|
|
|
|
|
// Calculate F-Max for variance homogeneity
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-24 23:17:58 +00:00
|
|
|
// Calculate Box test for covariance homogeneity
|
2020-10-24 21:21:15 +00:00
|
|
|
for i := 0 to NoSelected-1 do
|
|
|
|
for j := 0 to NoSelected-1 do
|
|
|
|
DetMat[i, j] := PooledMat[i, j];
|
|
|
|
Determ(DetMat, NoSelected, NoSelected, Det, errorcode);
|
2020-03-30 18:01:44 +00:00
|
|
|
if (Det > EPS) then
|
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
with AData do
|
|
|
|
begin
|
|
|
|
M1 := (NinGrp*NoAGrps*NoBGrps * ln(Det)) - Sum1;
|
|
|
|
C1 := (2.0 * NoSelected * NoSelected + 3.0 * NoSelected - 1.0) /
|
|
|
|
(6.0 * (NoSelected+1) * (NoAGrps * NoBGrps - 1.0));
|
|
|
|
C1 := C1 * ( (NoAGrps * NoBGrps * (1.0 / NinGrp)) - (1.0 / (NinGrp * NoAGrps * NoBGrps)));
|
|
|
|
f1 := (NoSelected * (NoSelected + 1.0) * (NoAGrps * NoBGrps - 1.0))/2.0;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
chi := (1.0 - C1) * M1;
|
2020-10-24 22:55:18 +00:00
|
|
|
ProbChi := 1.0 - ChiSquaredProb(chi, round(f1));
|
2020-03-30 18:01:44 +00:00
|
|
|
AReport.Add('Test that sample covariances are from same population:');
|
|
|
|
AReport.Add('');
|
2020-10-24 23:17:58 +00:00
|
|
|
AReport.Add('Chi-Squared: %0.3f with %d degrees of freedom.', [chi, round(f1)]);
|
2020-10-24 21:21:15 +00:00
|
|
|
AReport.Add('Probability of > Chi-Squared: %0.3f', [ProbChi]);
|
2020-03-30 18:01:44 +00:00
|
|
|
AReport.Add('');
|
2020-10-24 23:17:58 +00:00
|
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
2020-03-30 18:01:44 +00:00
|
|
|
AReport.Add('');
|
|
|
|
end else
|
2020-10-24 21:21:15 +00:00
|
|
|
ErrorMsg('Determinant of a pooled covariance AMatrix near 0.');
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
// test that pooled covariance has form of equal variances and equal covariances
|
|
|
|
//if (Det > 0.0e35) then // determinant of pooled covariance > 0
|
|
|
|
if (Det > EPS) then
|
|
|
|
begin
|
|
|
|
M2 := Det;
|
|
|
|
avgvar := 0.0;
|
2020-10-24 21:21:15 +00:00
|
|
|
for i := 0 to NoSelected-1 do
|
|
|
|
avgvar := avgvar + PooledMat[i, i];
|
2020-03-30 18:01:44 +00:00
|
|
|
avgvar := avgvar / NoSelected;
|
|
|
|
avgcov := 0.0;
|
|
|
|
for i := 1 to NoSelected-1 do
|
|
|
|
for j := i+1 to NoSelected do
|
|
|
|
avgcov := avgcov + PooledMat[i-1,j-1];
|
|
|
|
avgcov := avgcov / (NoSelected * (NoSelected - 1) / 2);
|
2020-10-24 21:21:15 +00:00
|
|
|
for i := 0 to NoSelected do
|
|
|
|
DetMat[i, i] := avgvar;
|
2020-03-30 18:01:44 +00:00
|
|
|
for i := 1 to NoSelected-1 do
|
|
|
|
begin
|
|
|
|
for j := i+1 to NoSelected do
|
|
|
|
begin
|
|
|
|
DetMat[i-1,j-1] := avgcov;
|
|
|
|
DetMat[j-1,i-1] := avgcov;
|
|
|
|
end;
|
|
|
|
end;
|
2020-10-24 22:55:18 +00:00
|
|
|
Determ(DetMat, NoSelected, NoSelected, Det, errorcode);
|
2020-03-30 18:01:44 +00:00
|
|
|
if (Det > EPS) then
|
|
|
|
begin
|
2020-10-25 10:21:35 +00:00
|
|
|
with AData do
|
|
|
|
begin
|
|
|
|
N := NoAGrps * NoBGrps * NinGrp;
|
|
|
|
p := NoAGrps * NoBGrps;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
quad := NoSelected * NoSelected + NoSelected - 4;
|
|
|
|
M2 := ln(M2 / Det);
|
|
|
|
M2 := -(N - p) * M2;
|
|
|
|
C2 := NoSelected * (NoSelected + 1) * (NoSelected + 1) * (2 * NoSelected - 3);
|
|
|
|
C2 := C2 / (6 * (N - p) * (NoSelected - 1) * quad);
|
|
|
|
f2 := quad / 2;
|
|
|
|
chi := (1.0 - C2) * M2;
|
2020-10-24 21:21:15 +00:00
|
|
|
ProbChi := 1.0 - ChiSquaredProb(chi, round(f2));
|
2020-03-30 18:01:44 +00:00
|
|
|
AReport.Add('Test that variance-covariances AMatrix has equal variances and equal covariances:');
|
|
|
|
AReport.Add('');
|
2020-10-24 23:17:58 +00:00
|
|
|
AReport.Add('Chi-Squared: %0.3f with %d degrees of freedom.', [chi, round(f2)]);
|
|
|
|
AReport.Add('Probability of > Chi-Squared: %.3f', [ProbChi]);
|
2020-03-30 18:01:44 +00:00
|
|
|
end else
|
2020-10-24 21:21:15 +00:00
|
|
|
ErrorMsg('Determinant of theoretical covariance AMatrix near zero.');
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-10-24 22:07:31 +00:00
|
|
|
FBoxTestsReportFrame.DisplayReport(AReport);
|
|
|
|
AReport.Clear;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-10-24 20:38:29 +00:00
|
|
|
|
2020-10-24 22:07:31 +00:00
|
|
|
procedure TABRAnovaForm.PlotMeans(AInteraction: TInteraction);
|
|
|
|
const
|
|
|
|
X_TITLE: array[TInteraction] of string = (
|
|
|
|
'B Treatment Group',
|
|
|
|
'C Treatment (within subjects) Group',
|
|
|
|
'C Treatment (within subjects) Group'
|
|
|
|
);
|
|
|
|
SERIES_TITLE: array[TInteraction] of string = (
|
|
|
|
'A%d',
|
|
|
|
'A%d',
|
|
|
|
'B%d'
|
|
|
|
);
|
|
|
|
var
|
|
|
|
serSource: TListChartSource;
|
2020-10-24 22:55:18 +00:00
|
|
|
i: Integer;
|
2020-10-24 22:07:31 +00:00
|
|
|
begin
|
2020-10-24 20:38:29 +00:00
|
|
|
case AInteraction of
|
|
|
|
AB: serSource := ListChartSource_AB;
|
|
|
|
AC: serSource := ListChartSource_AC;
|
|
|
|
BC: serSource := ListChartSource_BC;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 22:07:31 +00:00
|
|
|
FBarSeries.Source := serSource;
|
2020-10-25 10:21:35 +00:00
|
|
|
Set3DPlot(ThreeDChk.Checked);
|
2020-10-24 20:38:29 +00:00
|
|
|
|
2020-10-24 22:07:31 +00:00
|
|
|
ChartStyles.Styles.Clear;
|
|
|
|
for i := 0 to serSource.YCount-1 do
|
2020-10-24 20:38:29 +00:00
|
|
|
begin
|
|
|
|
with TChartStyle(ChartStyles.Styles.Add) do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 20:38:29 +00:00
|
|
|
Text := Format(SERIES_TITLE[AInteraction], [i+1]);
|
|
|
|
Brush.Color := DATA_COLORS[i mod Length(DATA_COLORS)];
|
|
|
|
UseBrush := true;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-10-24 20:38:29 +00:00
|
|
|
end;
|
|
|
|
|
2020-10-24 22:07:31 +00:00
|
|
|
FChartFrame.Chart.BottomAxis.Marks.Source := FBarSeries.Source;
|
2020-10-24 20:38:29 +00:00
|
|
|
FChartFrame.Chart.BottomAxis.Marks.Style := smsXValue;
|
|
|
|
FChartFrame.SetTitle('AxBxR ANOVA');
|
|
|
|
FChartFrame.SetXTitle(X_TITLE[AInteraction]);
|
|
|
|
FChartFrame.SetYTitle('Means');
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-10-24 20:38:29 +00:00
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
procedure TABRAnovaForm.PreparePlot(const AData: TABRAnovaData);
|
|
|
|
var
|
|
|
|
idx: Integer;
|
|
|
|
item: PChartDataItem;
|
|
|
|
i, j: Integer;
|
|
|
|
begin
|
|
|
|
FChartFrame.Clear;
|
|
|
|
ListChartSource_AB.Clear;
|
|
|
|
ListChartSource_AC.Clear;
|
|
|
|
ListChartSource_BC.Clear;
|
|
|
|
ChartStyles.Styles.Clear;
|
|
|
|
|
|
|
|
ListChartSource_AB.YCount := AData.NoAGrps;
|
|
|
|
for j := 0 to AData.NoBGrps-1 do
|
|
|
|
begin
|
|
|
|
idx := ListChartSource_AB.Add(j+1, 0);
|
|
|
|
item := ListChartSource_AB.Item[idx];
|
|
|
|
for i := 0 to AData.NoAGrps-1 do
|
|
|
|
item^.SetY(i, AData.ABSums[i, j] / (AData.NInGrp * NoSelected));
|
|
|
|
end;
|
|
|
|
|
|
|
|
ListChartSource_AC.YCount := AData.NoAGrps;
|
|
|
|
for j := 0 to NoSelected-1 do
|
|
|
|
begin
|
|
|
|
idx := ListChartSource_AC.Add(j+1, 0);
|
|
|
|
item := ListChartSource_AC.Item[idx];
|
|
|
|
for i := 0 to AData.NoAGrps-1 do
|
|
|
|
item^.SetY(i, AData.ACSums[i, j] / (AData.NInGrp * AData.NoBGrps));
|
|
|
|
end;
|
|
|
|
|
|
|
|
ListChartSource_BC.YCount := AData.NoBGrps;
|
|
|
|
for j := 0 to NoSelected-1 do
|
|
|
|
begin
|
|
|
|
idx := ListChartSource_BC.Add(j+1, 0);
|
|
|
|
item := ListChartSource_BC.Item[idx];
|
|
|
|
for i := 0 to AData.NoBGrps-1 do
|
|
|
|
item^.SetY(i, AData.BCSums[i, j] / (AData.NInGrp * AData.NoAGrps));
|
|
|
|
end;
|
|
|
|
|
|
|
|
FBarSeries := FChartFrame.PlotXY(ptBars, nil, nil, nil, nil, '', clDefault) as TBarSeries;
|
|
|
|
with FBarSeries do
|
|
|
|
begin
|
|
|
|
Legend.Multiplicity := lmStyle;
|
|
|
|
Stacked := false;
|
|
|
|
Styles := ChartStyles;
|
|
|
|
{$IF LCL_FullVersion >= 2010000}
|
|
|
|
DepthBrightnessDelta := -30;
|
|
|
|
{$IFEND}
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
procedure TABRAnovaForm.Reset;
|
|
|
|
var
|
|
|
|
i: integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-24 15:56:52 +00:00
|
|
|
inherited;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-24 21:21:15 +00:00
|
|
|
ListChartSource_AB.Clear;
|
|
|
|
ListChartSource_AC.Clear;
|
|
|
|
ListChartSource_BC.Clear;
|
|
|
|
|
2020-10-24 22:07:31 +00:00
|
|
|
BoxTestsPage.TabVisible := false;
|
2020-10-24 21:21:15 +00:00
|
|
|
ChartPage.TabVisible := false;
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
VarList.Items.Clear;
|
|
|
|
CList.Items.Clear;
|
|
|
|
ACodesEdit.Text := '';
|
|
|
|
BCodesEdit.Text := '';
|
|
|
|
for i := 1 to NoVariables do
|
2020-10-24 21:21:15 +00:00
|
|
|
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i, 0]);
|
2020-10-24 15:56:52 +00:00
|
|
|
PlotChk.Checked := false;
|
|
|
|
TestChk.Checked := false;
|
2020-10-24 21:21:15 +00:00
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
|
2020-10-25 10:21:35 +00:00
|
|
|
procedure TABRAnovaForm.Set3DPlot(AEnable: Boolean);
|
|
|
|
const
|
|
|
|
DEPTH: array[boolean] of Integer = (0, 20);
|
|
|
|
begin
|
|
|
|
if (FBarSeries <> nil) then
|
|
|
|
begin
|
|
|
|
FBarSeries.Depth := DEPTH[AEnable];
|
|
|
|
FChartFrame.Chart.LeftAxis.Grid.Visible := not AEnable;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TABRAnovaForm.ThreeDChkChange(Sender: TObject);
|
|
|
|
begin
|
|
|
|
Set3DPlot(ThreeDChk.Checked);
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
procedure TABRAnovaForm.UpdateBtnStates;
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
|
|
|
lSelected: Boolean;
|
|
|
|
i: Integer;
|
|
|
|
begin
|
2020-10-24 15:56:52 +00:00
|
|
|
inherited;
|
|
|
|
|
|
|
|
AInBtn.Enabled := (VarList.ItemIndex > -1) and (ACodesEdit.Text = '');
|
|
|
|
AOutBtn.Enabled := (ACodesEdit.Text <> '');
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
BInBtn.Enabled := (VarList.ItemIndex > -1) and (BCodesEdit.Text = '');
|
|
|
|
BOutBtn.Enabled := (BCodesEdit.Text <> '');
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
lSelected := false;
|
|
|
|
for i := 0 to VarList.Items.Count-1 do
|
|
|
|
if VarList.Selected[i] then
|
|
|
|
begin
|
|
|
|
lSelected := true;
|
|
|
|
break;
|
|
|
|
end;
|
|
|
|
CInBtn.Enabled := lSelected;
|
|
|
|
|
|
|
|
lSelected := false;
|
|
|
|
for i := 0 to CList.Items.Count-1 do
|
|
|
|
if CList.Selected[i] then
|
|
|
|
begin
|
|
|
|
lSelected := true;
|
|
|
|
break;
|
|
|
|
end;
|
|
|
|
COutBtn.Enabled := lSelected;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 15:56:52 +00:00
|
|
|
|
|
|
|
function TABRAnovaForm.Validate(out AMsg: String; out AControl: TWinControl): Boolean;
|
|
|
|
begin
|
|
|
|
Result := false;
|
|
|
|
|
|
|
|
if ACodesEdit.Text = '' then
|
|
|
|
begin
|
|
|
|
AMsg := 'Factor A variable not specified.';
|
|
|
|
AControl := ACodesEdit;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
if BCodesEdit.Text = '' then
|
|
|
|
begin
|
|
|
|
AMsg := 'Factor B variable not specified.';
|
|
|
|
AControl := BCodesEdit;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
|
2020-10-24 22:55:18 +00:00
|
|
|
if CList.Items.Count <= 1 then
|
2020-10-24 15:56:52 +00:00
|
|
|
begin
|
2020-10-24 22:55:18 +00:00
|
|
|
if CList.Items.Count = 0 then
|
|
|
|
AMsg := 'No Repeated Measures variable(s) specified.'
|
|
|
|
else
|
|
|
|
AMsg := 'There must be at least one Repeated Measures variable.';
|
2020-10-24 15:56:52 +00:00
|
|
|
AControl := CList;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
Result := true;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TABRAnovaForm.VarListDblClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
index: Integer;
|
|
|
|
s: String;
|
|
|
|
begin
|
|
|
|
index := VarList.ItemIndex;
|
|
|
|
if index > -1 then
|
|
|
|
begin
|
|
|
|
s := VarList.Items[index];
|
|
|
|
if ACodesEdit.Text = '' then
|
|
|
|
ACodesEdit.Text := s
|
|
|
|
else
|
|
|
|
if BCodesEdit.Text = '' then
|
|
|
|
BCodesEdit.Text := s
|
|
|
|
else
|
|
|
|
CList.Items.Add(s);
|
|
|
|
VarList.Items.Delete(index);
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
end.
|
|
|
|
|