You've already forked lazarus-ccr
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7893 8e941d3f-bd1b-0410-a28a-d453659cc2b4
1491 lines
44 KiB
ObjectPascal
1491 lines
44 KiB
ObjectPascal
// Use file "ancova.laz" for testing.
|
|
// Y --> Dependent Variable
|
|
// Group --> Fixed Factors
|
|
// X, Z ---> Covariables
|
|
|
|
unit ANCOVAUnit;
|
|
|
|
{$mode objfpc}{$H+}
|
|
{$WARN 6058 off : Call to subroutine "$1" marked as inline is not inlined}
|
|
{.$DEFINE ANCOVA_DEBUG}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF ANCOVA_DEBUG}
|
|
LazLogger,
|
|
{$ENDIF}
|
|
Classes, SysUtils, Forms, Controls, Graphics, StdCtrls, Buttons, ExtCtrls, LCLVersion,
|
|
ComCtrls, MainUnit, FunctionsLib, Globals, DataProcs,
|
|
MatrixLib, DictionaryUnit, ReportFrameUnit, BasicStatsReportAndChartFormUnit;
|
|
|
|
type
|
|
|
|
{ TAncovaForm }
|
|
|
|
TAncovaForm = class(TBasicStatsReportAndChartForm)
|
|
Bevel1: TBevel;
|
|
Bevel2: TBevel;
|
|
Plot3DChk: TCheckBox;
|
|
MultCompChk: TCheckBox;
|
|
PlotMeansChk: TCheckBox;
|
|
PrintInverseMatChk: TCheckBox;
|
|
CorrelationMatsChk: TCheckBox;
|
|
DescriptiveStatsChk: TCheckBox;
|
|
DepIn: TBitBtn;
|
|
DepOut: TBitBtn;
|
|
FixedIn: TBitBtn;
|
|
FixedOut: TBitBtn;
|
|
CovIn: TBitBtn;
|
|
CovOut: TBitBtn;
|
|
DepVar: TEdit;
|
|
OptionsGroup: TGroupBox;
|
|
Label1: TLabel;
|
|
Label2: TLabel;
|
|
Label3: TLabel;
|
|
FixedList: TListBox;
|
|
Label4: TLabel;
|
|
CovList: TListBox;
|
|
MultCompPage: TTabSheet;
|
|
VarList: TListBox;
|
|
procedure CovInClick(Sender: TObject);
|
|
procedure CovListDblClick(Sender: TObject);
|
|
procedure CovOutClick(Sender: TObject);
|
|
procedure DepInClick(Sender: TObject);
|
|
procedure DepOutClick(Sender: TObject);
|
|
procedure FixedInClick(Sender: TObject);
|
|
procedure FixedListDblClick(Sender: TObject);
|
|
procedure FixedOutClick(Sender: TObject);
|
|
procedure Plot3DChkChange(Sender: TObject);
|
|
procedure PlotMeansChkChange(Sender: TObject);
|
|
procedure VarListDblClick(Sender: TObject);
|
|
procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean);
|
|
|
|
private
|
|
NCases, NoSelected, NoFixed, NoCovs, DepColNo : integer;
|
|
ColNoSelected : IntDyneVec; // Grid col. no's of predictors
|
|
RowLabels, ColLabels : StrDyneVec;
|
|
CorMat : DblDyneMat; // correlation matrix
|
|
IndMat : DblDyneMat; // correlation matrix among independent variables
|
|
BetaWeights : DblDyneVec; // standardized regression weights
|
|
Means, Variances, StdDevs : DblDyneVec;
|
|
probout : double; // probability for removing a variable
|
|
Testout : boolean; // true if testing for retention of variables
|
|
plot : boolean; // if true, plot group means
|
|
StdErrEst : double; // standard error of estimate
|
|
multcomp : boolean; // if true make multiple comparisons
|
|
R2 : double; // squared multiple correlation coefficient
|
|
FixedCols : IntDyneVec; // grid columns of fixed variables
|
|
CovCols : IntDyneVec; // grid columns of covariates
|
|
mingrp, maxgrp : IntDyneVec; // min and max group codes
|
|
Block : IntDyneMat; // descriptors for group codings
|
|
// values 1 to 5 contain group min, max, startcol, endcol and no. of vectors
|
|
NoBlocks : integer; // number of vector blocks created for groups and inter.
|
|
errorcode : boolean; // returned by routines that use an errorcode
|
|
IndepIndex : IntDyneVec; // sequential number of predictors in corr. matrix
|
|
BlockLabel : StrDyneVec;
|
|
NoTestVecs : integer; // no. of vectors for group interactions with covariates
|
|
constant : double; // regression constant
|
|
noind : integer; // no. of independent variables in a regression analysis
|
|
BWeights : DblDyneVec; // raw regression weights
|
|
// BStdErrs : DblDyneVec; // standard errors of regression weights
|
|
// BTtests : DblDyneVec;
|
|
|
|
procedure GetParms;
|
|
procedure CodeGroups;
|
|
procedure GenInteractions;
|
|
procedure DoRegs(AReport: TStrings);
|
|
procedure CleanUp;
|
|
procedure EntryOpt1(AReport: TStrings);
|
|
procedure GenCovInteracts;
|
|
procedure AdjustMeans(AReport: TStrings);
|
|
procedure MultCompare;
|
|
|
|
private
|
|
FMultCompReportFrame: TReportFrame;
|
|
FChartCombobox: TCombobox;
|
|
FMeansPlotData: DblDyneMat;
|
|
FAdjMeansPlotData: DblDyneMat;
|
|
procedure PopulateChartCombobox;
|
|
procedure SelectPlot(Sender: TObject);
|
|
|
|
protected
|
|
procedure AdjustConstraints; override;
|
|
procedure Compute; override;
|
|
procedure UpdateBtnStates; override;
|
|
function Validate(out AMsg: String; out AControl: TWinControl): Boolean; override;
|
|
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
procedure Reset; override;
|
|
end;
|
|
|
|
var
|
|
AncovaForm: TAncovaForm;
|
|
|
|
|
|
implementation
|
|
|
|
{$R *.lfm}
|
|
|
|
uses
|
|
Math,
|
|
TAChartUtils, TACustomSeries, TASeries, TAGraph,
|
|
Utils, MathUnit, ChartFrameUnit;
|
|
|
|
|
|
{ TAncovaForm }
|
|
|
|
constructor TAncovaForm.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
|
|
InitToolbar(FReportFrame.ReportToolbar, tpTop);
|
|
FReportFrame.ClearBorderSpacings;
|
|
|
|
FMultCompReportFrame := TReportFrame.Create(self);
|
|
FMultCompReportFrame.Parent := MultCompPage;
|
|
FMultCompReportFrame.Align := alClient;
|
|
|
|
FChartFrame.Chart.Margins.Bottom := 0;
|
|
FChartFrame.Chart.BottomAxis.AxisPen.Visible := true;
|
|
FChartFrame.Chart.BottomAxis.ZPosition := 1;
|
|
FChartFrame.Chart.BottomAxis.Grid.Visible := false;
|
|
AddComboboxToToolbar(FChartFrame.ChartToolbar, 'Plots:', FChartCombobox);
|
|
FChartCombobox.OnSelect := @SelectPlot;
|
|
|
|
ChartPage.PageIndex := PageControl.PageCount-1;
|
|
PageControl.ActivePageIndex := 0;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.AdjustConstraints;
|
|
begin
|
|
inherited;
|
|
ParamsPanel.Constraints.MinHeight := DepIn.Top + 6*DepIn.Height +
|
|
3* DepOut.BorderSpacing.Top + 2*DepOut.BorderSpacing.Bottom + Label4.Height * 2 + // not 100% exact...
|
|
VarList.BorderSpacing.Bottom + OptionsGroup.Height +
|
|
ButtonBevel.Height + CloseBtn.BorderSpacing.Top + CloseBtn.Height;
|
|
ParamsPanel.Constraints.MinWidth := Max(
|
|
OptionsGroup.Width,
|
|
4*CloseBtn.Width + 3*CloseBtn.BorderSpacing.Left
|
|
);
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.Compute;
|
|
var
|
|
lReport: TStrings;
|
|
begin
|
|
NoFixed := FixedList.Items.Count;
|
|
NoCovs := CovList.Items.Count;
|
|
|
|
lReport := TStringList.Create;
|
|
try
|
|
GetParms;
|
|
CodeGroups;
|
|
GenInteractions;
|
|
GenCovInteracts;
|
|
DoRegs(lReport);
|
|
FReportFrame.DisplayReport(lReport);
|
|
finally
|
|
CleanUp;
|
|
lReport.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TAncovaForm.CovInClick(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
begin
|
|
i := 0;
|
|
while i < VarList.Items.Count do
|
|
begin
|
|
if VarList.Selected[i] then
|
|
begin
|
|
CovList.Items.Add(VarList.Items[i]);
|
|
VarList.Items.Delete(i);
|
|
i := 0;
|
|
end else
|
|
inc(i);
|
|
end;
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.CovListDblClick(Sender: TObject);
|
|
var
|
|
index: Integer;
|
|
begin
|
|
index := CovList.ItemIndex;
|
|
if index > -1 then
|
|
begin
|
|
VarList.Items.Add(CovList.Items[index]);
|
|
CovList.Items.Delete(index);
|
|
UpdateBtnStates;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.CovOutClick(Sender: TObject);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
i := 0;
|
|
while i < CovList.Items.Count do
|
|
begin
|
|
if CovList.Selected[i] then
|
|
begin
|
|
Varlist.Items.Add(CovList.Items[i]);
|
|
CovList.Items.Delete(i);
|
|
i := 0;
|
|
end else
|
|
inc(i);
|
|
end;
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.DepInClick(Sender: TObject);
|
|
var
|
|
index: integer;
|
|
begin
|
|
index := VarList.ItemIndex;
|
|
if (index > -1) and (DepVar.Text = '') then
|
|
begin
|
|
DepVar.Text := VarList.Items[index];
|
|
VarList.Items.Delete(index);
|
|
end;
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.DepOutClick(Sender: TObject);
|
|
begin
|
|
if DepVar.Text <> '' then
|
|
begin
|
|
VarList.Items.Add(DepVar.Text);
|
|
DepVar.Text := '';
|
|
end;
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.FixedInClick(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
begin
|
|
i := 0;
|
|
while i < VarList.Items.Count do
|
|
begin
|
|
if VarList.Selected[i] then
|
|
begin
|
|
FixedList.Items.Add(VarList.Items[i]);
|
|
VarList.Items.Delete(i);
|
|
i := 0;
|
|
end else
|
|
inc(i);
|
|
end;
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.FixedListDblClick(Sender: TObject);
|
|
var
|
|
index: Integer;
|
|
begin
|
|
index := FixedList.ItemIndex;
|
|
if index > -1 then
|
|
begin
|
|
VarList.Items.Add(FixedList.Items[index]);
|
|
FixedList.Items.Delete(index);
|
|
UpdateBtnStates;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.FixedOutClick(Sender: TObject);
|
|
var
|
|
i : integer;
|
|
begin
|
|
i := 0;
|
|
while i < FixedList.Items.Count do
|
|
begin
|
|
if FixedList.Selected[i] then
|
|
begin
|
|
VarList.Items.Add(FixedList.Items[i]);
|
|
FixedList.Items.Delete(i);
|
|
i := 0;
|
|
end else
|
|
inc(i);
|
|
end;
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.Plot3DChkChange(Sender: TObject);
|
|
var
|
|
ser: TBasicChartSeries;
|
|
begin
|
|
if (FChartFrame = nil) or (FChartFrame.Chart.SeriesCount = 0) then
|
|
exit;
|
|
|
|
ser := FChartFrame.Chart.Series[0];
|
|
if (ser is TBarSeries) then
|
|
begin
|
|
if Plot3dChk.Checked then
|
|
TBarSeries(ser).Depth := 20
|
|
else
|
|
TBarSeries(ser).Depth := 0;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.PlotMeansChkChange(Sender: TObject);
|
|
begin
|
|
Plot3DChk.Enabled := PlotMeansChk.Checked;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.GetParms;
|
|
var
|
|
i, j: integer;
|
|
begin
|
|
SetLength(ColNoSelected, NoVariables);
|
|
SetLength(FixedCols, NoFixed);
|
|
SetLength(CovCols, NoCovs);
|
|
SetLength(mingrp, NoFixed);
|
|
SetLength(maxgrp, NoFixed);
|
|
SetLength(Block, 100, 5);
|
|
SetLength(BlockLabel, 100);
|
|
|
|
NoSelected := 0;
|
|
NoBlocks := 0;
|
|
plot := PlotMeansChk.Checked;
|
|
multcomp := MultCompChk.Checked;
|
|
|
|
for i := 1 to NoVariables do
|
|
begin
|
|
if DepVar.Text = OS3MainFrm.DataGrid.Cells[i,0] then
|
|
begin
|
|
DepColNo := i;
|
|
ColNoSelected[0] := i;
|
|
NoSelected := 1;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
for i := 0 to NoFixed - 1 do
|
|
begin
|
|
for j := 1 to NoVariables do
|
|
begin
|
|
if FixedList.Items.Strings[i] = OS3MainFrm.DataGrid.Cells[j,0] then
|
|
begin
|
|
FixedCols[i] := j;
|
|
ColNoSelected[NoSelected] := j;
|
|
NoSelected := NoSelected + 1;
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
for i := 0 to NoCovs - 1 do
|
|
begin
|
|
for j := 1 to NoVariables do
|
|
begin
|
|
if CovList.Items.Strings[i] = OS3MainFrm.DataGrid.Cells[j,0] then
|
|
begin
|
|
CovCols[i] := j;
|
|
ColNoSelected[NoSelected] := j;
|
|
NoSelected := NoSelected + 1;
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// create a "Block" for each covariate
|
|
for i := 0 to NoCovs-1 do
|
|
begin
|
|
NoBlocks := NoBlocks + 1;
|
|
Block[i,0] := 0; // group min
|
|
Block[i,1] := 0; // group max
|
|
Block[i,2] := CovCols[i]; // start column in grid
|
|
Block[i,3] := CovCols[i]; // end column in grid
|
|
Block[i,4] := 1; // no. of vectors
|
|
BlockLabel[i] := 'Cov' + IntToStr(i);
|
|
end;
|
|
end;
|
|
|
|
procedure TAncovaForm.CodeGroups;
|
|
var
|
|
col, i, j, value: integer;
|
|
factlabel, cellstring: string;
|
|
startcol: Integer = 0; // to silence the compiler
|
|
endcol: Integer = 0;
|
|
noVectors: Integer = 0;
|
|
begin
|
|
// create a block for code vectors of each fixed variable
|
|
for i := 0 to NoFixed-1 do
|
|
begin
|
|
col := FixedCols[i];
|
|
factlabel := chr(ord('A')+i);
|
|
mingrp[i] := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col,1])));
|
|
maxgrp[i] := mingrp[i];
|
|
for j := 1 to NoCases do
|
|
begin
|
|
if not GoodRecord(j,NoSelected,ColNoSelected) then continue;
|
|
cellstring := Trim(OS3MainFrm.DataGrid.Cells[col,j]);
|
|
value := round(StrToFloat(cellstring));
|
|
if value < mingrp[i] then mingrp[i] := value;
|
|
if value > maxgrp[i] then maxgrp[i] := value;
|
|
end;
|
|
|
|
// create fixed effect coding for levels - 1 of the fixed effect var.
|
|
EffectCode(col, mingrp[i], maxgrp[i], factlabel, startcol, endcol, novectors);
|
|
NoBlocks := NoBlocks + 1;
|
|
Block[NoBlocks-1,0] := mingrp[i];
|
|
Block[NoBlocks-1,1] := maxgrp[i];
|
|
Block[NoBlocks-1,2] := startcol;
|
|
Block[NoBlocks-1,3] := endcol;
|
|
Block[NoBlocks-1,4] := novectors;
|
|
BlockLabel[NoBlocks-1] := factlabel;
|
|
end; // next factor block
|
|
end;
|
|
|
|
procedure TAncovaForm.GenInteractions;
|
|
type
|
|
Twoway = array[0..9,0..1] of integer;
|
|
Threeway = array[0..9,0..2] of integer;
|
|
Fourway = array[0..4,0..3] of integer;
|
|
const
|
|
Twoways: Twoway = (
|
|
(1,2), (1,3), (2,3), (1,4), (2,4), (3,4), (1,5), (2,5), (3,5), (4,5)
|
|
);
|
|
Threeways: Threeway = (
|
|
(1,2,3), (1,2,4), (1,3,4), (2,3,4), (1,2,5),
|
|
(1,3,5), (1,4,5), (2,3,5), (2,4,5), (3,4,5)
|
|
);
|
|
Fourways: Fourway = (
|
|
(1,2,3,4), (1,2,3,5), (1,2,4,5), (1,3,4,5), (2,3,4,5)
|
|
);
|
|
var
|
|
i, j, k, l, m, n, col, value: integer;
|
|
labelstr: string;
|
|
startcol, endcol, novectors, oldnovars: integer;
|
|
cell1, cell2, cell3, cell4: string;
|
|
TwoWayCombos, ThreeWayCombos, FourwayCombos: double;
|
|
Block1, Block2, Block3, Block4, Start1, End1, Start2, End2, Start3, End3: integer;
|
|
Start4, End4: integer;
|
|
begin
|
|
novectors := 0;
|
|
|
|
// Do two-way interactions
|
|
if NoFixed < 2 then
|
|
exit;
|
|
TwoWayCombos := round(combos(2.0, NoFixed));
|
|
oldnovars := NoVariables;
|
|
for i := 0 to round(TwoWayCombos)-1 do
|
|
begin
|
|
Block1 := TwoWays[i,0] + NoCovs - 1;
|
|
Block2 := TwoWays[i,1] + NoCovs - 1;
|
|
Start1 := Block[Block1,2];
|
|
End1 := Block[Block1,3];
|
|
Start2 := Block[Block2,2];
|
|
End2 := Block[Block2,3];
|
|
oldnovars := NoVariables;
|
|
startcol := Block[NoBlocks-1,3] + 1;
|
|
col := NoVariables;
|
|
for j := Start1 to End1 do
|
|
begin
|
|
for k := Start2 to End2 do
|
|
begin
|
|
col := col + 1;
|
|
novectors := novectors + 1;
|
|
DictionaryFrm.NewVar(col);
|
|
labelstr := OS3MainFrm.DataGrid.Cells[j,0] + 'x';
|
|
labelstr := labelstr + OS3MainFrm.DataGrid.Cells[k,0];
|
|
OS3MainFrm.DataGrid.Cells[col,0] := labelstr;
|
|
DictionaryFrm.DictGrid.Cells[1,col] := labelstr;
|
|
for m := 1 to NoCases do
|
|
begin
|
|
if not GoodRecord(m,NoSelected,ColNoSelected) then Continue;
|
|
cell1 := Trim(OS3MainFrm.DataGrid.Cells[j,m]);
|
|
cell2 := Trim(OS3MainFrm.DataGrid.Cells[k,m]);
|
|
value := round(StrToFloat(cell1)) * round(StrToFloat(cell2));
|
|
OS3MainFrm.DataGrid.Cells[col,m] := IntToStr(value);
|
|
end;
|
|
end;
|
|
endcol := col;
|
|
NoBlocks := NoBlocks + 1;
|
|
Block[NoBlocks-1,0] := 0; // zeroes for interactions
|
|
Block[NoBlocks-1,1] := 0; // zeroes for interactions
|
|
Block[NoBlocks-1,2] := startcol; // grid start col for 2-way interactions
|
|
Block[NoBlocks-1,3] := endcol; // grid end col for 2-way interactions
|
|
Block[NoBlocks-1,4] := novectors; // no. of vectors for 2-way interaction
|
|
BlockLabel[NoBlocks-1] := BlockLabel[Block1] + 'x' + BlockLabel[Block2];
|
|
NoVariables := oldnovars + novectors;
|
|
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
|
|
novectors := 0;
|
|
end; // end of interaction of fixed effect vectors j and fixed effect vectors k
|
|
end; // end of 2 way interactions
|
|
|
|
// do 3-way interactions using group vectors and two way interaction vectors
|
|
if (NoFixed < 3) then
|
|
exit;
|
|
ThreeWayCombos := Combos(3.0, NoFixed);
|
|
for i := 0 to round(ThreeWayCombos)-1 do
|
|
begin
|
|
startcol := Block[NoBlocks-1,3] + 1; // next column after last block
|
|
col := NoVariables;
|
|
Block1 := ThreeWays[i,0] + NoCovs - 1;
|
|
Block2 := ThreeWays[i,1] + NoCovs - 1;
|
|
Block3 := ThreeWays[i,2] + NoCovs - 1;
|
|
Start1 := Block[Block1,2];
|
|
End1 := Block[Block1,3];
|
|
Start2 := Block[Block2,2];
|
|
End2 := Block[Block2,3];
|
|
Start3 := Block[Block3,2];
|
|
End3 := Block[Block3,3];
|
|
oldnovars := NoVariables;
|
|
novectors := 0;
|
|
for j := Start1 to End1 do
|
|
begin
|
|
for k := Start2 to End2 do
|
|
begin
|
|
for l := Start3 to End3 do // no. vectors in first factor
|
|
begin
|
|
col := col + 1;
|
|
novectors := novectors + 1;
|
|
DictionaryFrm.NewVar(col);
|
|
labelstr := OS3MainFrm.DataGrid.Cells[j,0] + 'x';
|
|
labelstr := labelstr + OS3MainFrm.DataGrid.Cells[k,0];
|
|
labelstr := labelstr + 'x' + OS3MainFrm.DataGrid.Cells[l,0];
|
|
OS3MainFrm.DataGrid.Cells[col,0] := labelstr;
|
|
DictionaryFrm.DictGrid.Cells[1,col] := labelstr;
|
|
for m := 1 to NoCases do
|
|
begin
|
|
if not GoodRecord(m,NoSelected,ColNoSelected) then Continue;
|
|
cell1 := Trim(OS3MainFrm.DataGrid.Cells[j,m]);
|
|
cell2 := Trim(OS3MainFrm.DataGrid.Cells[k,m]);
|
|
cell3 := Trim(OS3MainFrm.DataGrid.Cells[l,m]);
|
|
value := round(StrToFloat(cell1)) * round(StrToFloat(cell2)) * round(StrToFloat(cell3));
|
|
OS3MainFrm.DataGrid.Cells[col,m] := IntToStr(value);
|
|
end; // next case m
|
|
end; // next third variable
|
|
end; // next second variable
|
|
end; // end of interaction of fixed effects vectors for j, k and l
|
|
endcol := col; // last grid column containing three-way interaction vectors
|
|
NoBlocks := NoBlocks + 1;
|
|
Block[NoBlocks-1,0] := 0; // zeroes for interactions
|
|
Block[NoBlocks-1,1] := 0; // zeroes for interactions
|
|
Block[NoBlocks-1,2] := startcol; // grid start col for 2-way interactions
|
|
Block[NoBlocks-1,3] := endcol; // grid end col for 2-way interactions
|
|
Block[NoBlocks-1,4] := novectors; // no. of vectors for 2-way interaction
|
|
BlockLabel[NoBlocks-1] := BlockLabel[Block1] + 'x' + BlockLabel[Block2] + 'x' + BlockLabel[Block3];
|
|
NoVariables := oldnovars + novectors;
|
|
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
|
|
end; // end of three way interactions
|
|
|
|
// do 4-way interactions using group and 3-way interaction vectors
|
|
if (NoFixed < 4) then
|
|
exit;
|
|
FourWayCombos := combos(4.0,NoFixed);
|
|
for i := 0 to round(FourWayCombos) - 1 do
|
|
begin
|
|
startcol := Block[NoBlocks-1][3] + 1;
|
|
col := NoVariables;
|
|
Block1 := FourWays[i][0] + NoCovs - 1; // block # for first fixed effect
|
|
Block2 := FourWays[i][1] + NoCovs - 1; // block # for second fixed effect
|
|
Block3 := FourWays[i][2] + NoCovs - 1; // block # for third fixed effect
|
|
Block4 := FourWays[i][3] + NoCovs - 1; // block # for fourth fixed effect
|
|
Start1 := Block[Block1][2];
|
|
End1 := Block[Block1][3];
|
|
Start2 := Block[Block2][2];
|
|
End2 := Block[Block2][3];
|
|
Start3 := Block[Block3][2];
|
|
End3 := Block[Block3][3];
|
|
Start4 := Block[Block4][2];
|
|
End4 := Block[Block4][3];
|
|
oldnovars := NoVariables;
|
|
novectors := 0;
|
|
for j := Start1 to End1 do // vector in first fixed factor
|
|
begin
|
|
for k := Start2 to End2 do // vector in second fixed factor
|
|
begin
|
|
for l := Start3 to End3 do // vector in third fixed factor
|
|
begin
|
|
for m := Start4 to End4 do // vecotr in fourth fixed factor
|
|
begin
|
|
col := col + 1;
|
|
novectors := novectors + 1;
|
|
DictionaryFrm.NewVar(col);
|
|
labelstr := OS3MainFrm.DataGrid.Cells[j,0] + 'x';
|
|
labelstr := labelstr + OS3MainFrm.DataGrid.Cells[k,0];
|
|
labelstr := labelstr + 'x' + OS3MainFrm.DataGrid.Cells[l,0];
|
|
OS3MainFrm.DataGrid.Cells[col,0] := labelstr;
|
|
DictionaryFrm.DictGrid.Cells[1,col] := labelstr;
|
|
for n := 1 to NoCases do
|
|
begin
|
|
cell1 := Trim(OS3MainFrm.DataGrid.Cells[j,n]);
|
|
cell2 := Trim(OS3MainFrm.DataGrid.Cells[k,n]);
|
|
cell3 := Trim(OS3MainFrm.DataGrid.Cells[l,n]);
|
|
cell4 := Trim(OS3MainFrm.DataGrid.Cells[m,n]);
|
|
value := round(StrToFloat(cell1)) *
|
|
round(StrToFloat(cell2)) *
|
|
round(StrToFloat(cell3)) *
|
|
round(StrToFloat(cell4));
|
|
OS3MainFrm.DataGrid.Cells[col,n] := IntToStr(value);
|
|
end; // next case n
|
|
end; // next fourth vector m
|
|
end; // next third vector
|
|
end; // next second vector
|
|
end; // end of interaction of fixed effects vectors for j, k and l and m
|
|
|
|
endcol := col; // last grid column containing four-way interaction vectors
|
|
NoBlocks := NoBlocks + 1;
|
|
Block[NoBlocks-1][0] := 0; // zeroes for interactions
|
|
Block[NoBlocks-1][1] := 0; // zeroes for interactions
|
|
Block[NoBlocks-1][2] := startcol; // grid start col for 4-way interactions
|
|
Block[NoBlocks-1][3] := endcol; // grid end col for 4-way interactions
|
|
Block[NoBlocks-1][4] := novectors; // no. of vectors for 2-way interaction
|
|
BlockLabel[NoBlocks-1] := BlockLabel[Block1] + 'x' +
|
|
BlockLabel[Block2] + 'x' +
|
|
BlockLabel[Block3] + 'x' + BlockLabel[Block4];
|
|
NoVariables := oldnovars + novectors;
|
|
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
|
|
end; // end of four-way combinations
|
|
end;
|
|
|
|
procedure TAncovaForm.DoRegs(AReport: TStrings);
|
|
var
|
|
count: integer;
|
|
i, j: integer;
|
|
begin
|
|
{$IFDEF ANCOVA_DEBUG}
|
|
DebugLn('ENTER DoRegs');
|
|
{$ENDIF}
|
|
|
|
// get count of variables used
|
|
count := 0;
|
|
for i := 0 to NoBlocks - 1 do
|
|
for j := 0 to Block[i,4] do count := count + 1;
|
|
|
|
{$IFDEF ANCOVA_DEBUG}
|
|
WriteLn('DoRegs: Count = ', count);
|
|
{$ENDIF}
|
|
|
|
SetLength(BetaWeights,count+1);
|
|
SetLength(BWeights,count+2);
|
|
// SetLength(BStdErrs,count+1);
|
|
// SetLength(BTtests,count+1);
|
|
SetLength(Means,count+1);
|
|
SetLength(Variances,count+1);
|
|
SetLength(StdDevs,count+1);
|
|
SetLength(RowLabels,count+1);
|
|
SetLength(ColLabels,count+1);
|
|
SetLength(Cormat,count+1,count+1);
|
|
SetLength(Indmat,count+1,count+1);
|
|
SetLength(IndepIndex,count+1);
|
|
SetLength(ColNoSelected,count+1);
|
|
|
|
Testout := false;
|
|
Probout := 0.99;
|
|
AReport.Add(DIVIDER_AUTO);
|
|
AReport.Add('ANALYSIS OF COVARIANCE USING MULTIPLE REGRESSION');
|
|
AReport.Add(DIVIDER_AUTO);
|
|
AReport.Add('');
|
|
AReport.Add('File Analyzed: ' + OS3MainFrm.FileNameEdit.Text);
|
|
AReport.Add('');
|
|
|
|
EntryOpt1(AReport); // factors, interactions and covariats concurrently
|
|
|
|
IndepIndex := nil;
|
|
{$IFDEF ANCOVA_DEBUG}
|
|
DebugLn('EXIT DoRegs');
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TAncovaForm.CleanUp;
|
|
begin
|
|
Indmat := nil;
|
|
Cormat := nil;
|
|
ColLabels := nil;
|
|
RowLabels := nil;
|
|
StdDevs := nil;
|
|
Variances := nil;
|
|
Means := nil;
|
|
// BTtests := nil;
|
|
// BStdErrs := nil;
|
|
BWeights := nil;
|
|
BetaWeights := nil;
|
|
maxgrp := nil;
|
|
mingrp := nil;
|
|
CovCols := nil;
|
|
FixedCols := nil;
|
|
ColNoSelected := nil
|
|
end;
|
|
|
|
procedure TAncovaForm.EntryOpt1(AReport: TStrings);
|
|
var
|
|
i, j, k, col, count: integer;
|
|
Title: string;
|
|
FullR2: double;
|
|
F: double;
|
|
Prob: double;
|
|
df1, df2: double;
|
|
SSGroups: double;
|
|
MSGroups: double;
|
|
SSError: double;
|
|
MSError: double;
|
|
SSTotal: double;
|
|
// SSExplained: double;
|
|
SSGrpTot: double = 0.0;
|
|
tProbs: DblDyneVec = nil;
|
|
BTtests: DblDyneVec = nil;
|
|
BStdErrs: DblDyneVec = nil; // standard errors of regression weights
|
|
localReport: TStrings;
|
|
begin
|
|
{$IFDEF ANCOVA_DEBUG}
|
|
DebugLn('ENTER EntryOpt1');
|
|
{$ENDIF}
|
|
|
|
// Factors, interactions and covariates concurrently (full model)
|
|
// Get grid column numbers of all vectors and dependent variable
|
|
|
|
AReport.Add('');
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
AReport.Add('MODEL FOR TESTING ASSUMPTION OF ZERO INTERACTIONS WITH COVARIATES');
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
AReport.Add('');
|
|
|
|
count := 0;
|
|
for i := 1 to NoBlocks do // no. of vector blocks
|
|
begin
|
|
for j := 1 to Block[i-1,4] do // no of vectors in block
|
|
begin
|
|
col := Block[i-1,2] + j - 1; // count from beginning col.
|
|
count := count + 1;
|
|
ColNoSelected[count-1] := col;
|
|
IndepIndex[count-1] := count;
|
|
RowLabels[count-1] := OS3MainFrm.DataGrid.Cells[col,0];
|
|
end;
|
|
end;
|
|
count := count + 1;
|
|
noind := count - 1;
|
|
ColNoSelected[count-1] := DepColNo;
|
|
IndepIndex[count-1] := count;
|
|
RowLabels[count-1] := OS3MainFrm.DataGrid.Cells[DepColNo,0];
|
|
|
|
// Get correlation matrix (note: dependent is last variable)
|
|
Correlations(count,ColNoSelected,CorMat, Means, Variances, StdDevs, errorcode, NCases);
|
|
if CorrelationMatsChk.Checked then
|
|
begin
|
|
title := 'CORRELATION MATRIX';
|
|
MatPrint(CorMat, count, count, title, RowLabels, RowLabels, NCases, AReport);
|
|
end;
|
|
|
|
if DescriptiveStatsChk.Checked then
|
|
begin
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
DynVectorPrint(means, count, 'MEANS', RowLabels, NoCases, AReport);
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
AReport.Add('');
|
|
DynVectorPrint(variances, count, 'VARIANCES', RowLabels, NoCases, AReport);
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
AReport.Add('');
|
|
DynVectorPrint(stdDevs, count, 'STANDARD DEVIATIONS', RowLabels, NoCases, AReport);
|
|
end;
|
|
|
|
// Get regression
|
|
SetLength(tProbs, count);
|
|
SetLength(BStdErrs, noind+1);
|
|
SetLength(BTtests, noind+1);
|
|
MReg(
|
|
noind, ColNoSelected, DepColNo, RowLabels ,Means, Variances, StdDevs,
|
|
BWeights, BetaWeights, BStdErrs, BTtests, tProbs, R2, StdErrEst, NCases, errorcode,
|
|
false, AReport
|
|
);
|
|
if not ErrorCode then
|
|
begin
|
|
FullR2 := R2;
|
|
SSTotal := Variances[count-1] * (NCases - 1);
|
|
SSGroups := FullR2 * SSTotal;
|
|
SSError := (1.0 - FullR2) * SSTotal;
|
|
df1 := noind;
|
|
df2 := NCases - noind - 1;
|
|
MSGroups := SSGroups / df1;
|
|
MSError := SSError / df2;
|
|
F := MSGroups / MSError;
|
|
Prob := ProbF(F, df1, df2);
|
|
AReport.Add('');
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
AReport.Add('');
|
|
AReport.Add('Analysis of Variance for the Model to Test Regression Homogeneity');
|
|
AReport.Add(' SOURCE Deg.F. SS MS F Prob>F');
|
|
AReport.Add('%10s %10.0f %10.2f %10.2f %10.3f %10.4f', ['Explained', df1, SSGroups, MSGroups, F, Prob]);
|
|
AReport.Add('%10s %10.0f %10.2f %10.2f', ['Error', df2, SSError, MSError]);
|
|
AReport.Add('%10s %10d %10.2f', ['Total', NCases-1, SSTotal]);
|
|
AReport.Add('');
|
|
AReport.Add('%12s %10.3f',['R Squared = ',R2]);
|
|
AReport.Add('');
|
|
end;
|
|
|
|
// Now do analysis without the interactions (Ancova model)
|
|
AReport.Add('');
|
|
AReport.Add(DIVIDER_AUTO);
|
|
AReport.Add('MODEL FOR ANALYSIS OF COVARIANCE');
|
|
AReport.Add(DIVIDER_AUTO);;
|
|
AReport.Add('');
|
|
|
|
count := 0;
|
|
for i := 1 to NoBlocks - 1 do // no. of vector blocks
|
|
begin
|
|
for j := 1 to Block[i-1,4] do // no of vectors in block
|
|
begin
|
|
col := Block[i-1,2] + j - 1; // count from beginning col.
|
|
count := count + 1;
|
|
ColNoSelected[count-1] := col;
|
|
IndepIndex[count-1] := count;
|
|
RowLabels[count-1] := OS3MainFrm.DataGrid.Cells[col,0];
|
|
end;
|
|
end;
|
|
count := count + 1;
|
|
noind := count - 1;
|
|
ColNoSelected[count-1] := DepColNo;
|
|
IndepIndex[count-1] := count;
|
|
RowLabels[count-1] := OS3MainFrm.DataGrid.Cells[DepColNo,0];
|
|
|
|
// Get correlation matrix (note dependent is last variable)
|
|
Correlations(count,ColNoSelected,Cormat,Means,Variances,StdDevs,errorcode,NCases);
|
|
// save in IndMat
|
|
for i := 0 to count-1 do
|
|
for j := 0 to count - 1 do
|
|
IndMat[i,j] := Cormat[i,j];
|
|
|
|
if CorrelationMatsChk.Checked then
|
|
begin
|
|
AReport.Add('');
|
|
Title := 'Correlation Matrix';
|
|
MatPrint(Cormat, count, count, title, RowLabels, RowLabels, NCases, AReport);
|
|
end;
|
|
|
|
if DescriptiveStatsChk.Checked then
|
|
begin
|
|
AReport.Add('');
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
DynVectorPrint(Means, count, 'MEANS', RowLabels, NCases, AReport);
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
DynVectorPrint(Variances, count, 'VARIANCES', RowLabels, NCases, AReport);
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
DynVectorPrint(StdDevs, count, 'STANDARD DEVIATIONS', RowLabels, NCases, AReport);
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
AReport.Add('');
|
|
end;
|
|
|
|
// Get regression
|
|
SetLength(BStdErrs, noind+1);
|
|
SetLength(BTtests, noind+1);
|
|
|
|
MReg(
|
|
noind, ColNoSelected, DepColNo, RowLabels, Means, Variances, StdDevs,
|
|
BWeights, BetaWeights, BStdErrs, BTtests, tProbs, R2, StdErrEst, NCases,
|
|
errorcode, false, AReport
|
|
);
|
|
|
|
if not ErrorCode then
|
|
begin
|
|
// test differences between previous and current models (= beta test)
|
|
constant := BWeights[noind];
|
|
df1 := NoTestVecs;
|
|
F := ((FullR2 - R2) / df1) / ((1.0 - FullR2) / df2);
|
|
Prob := probf(F,df1,df2);
|
|
AReport.Add('');
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
AReport.Add('');
|
|
AReport.Add('Test for Homogeneity of Group Regression Coefficients');
|
|
AReport.Add('Change in R2 = %6.4f. F = %10.3f Prob.> F = %6.4f with d.f. %8.0f and %8.0f', [(FullR2 - R2), F, Prob, df1, df2]);
|
|
AReport.Add('');
|
|
AReport.Add('%12s %10.3f',['R Squared = ', R2]);
|
|
|
|
FullR2 := R2;
|
|
SSTotal := Variances[count-1] * (NCases - 1);
|
|
SSGroups := FullR2 * SSTotal;
|
|
SSError := (1.0 - FullR2) * SSTotal;
|
|
df1 := noind;
|
|
df2 := NCases - noind - 1;
|
|
MSGroups := SSGroups / df1;
|
|
MSError := SSError / df2;
|
|
|
|
// obtain Adjusted means
|
|
// AdjustMeans(self);
|
|
// Make Comparisons among means
|
|
// if multcomp then MultCompare(self);
|
|
F := MSGroups / MSError;
|
|
Prob := probf(F,df1,df2);
|
|
AReport.Add('');
|
|
AReport.Add(DIVIDER_AUTO);
|
|
AReport.Add('');
|
|
AReport.Add('Analysis of Variance for the ANCOVA Model');
|
|
AReport.Add(' SOURCE Deg.F. SS MS F Prob>F ');
|
|
AReport.Add('---------- ---------- ---------- ---------- ---------- ----------');
|
|
AReport.Add('%10s %10.0f %10.2f %10.2f %10.3f %10.4f', ['Explained', df1, SSGroups, MSGroups, F, Prob]);
|
|
AReport.Add('%10s %10.0f %10.2f %10.2f', ['Error', df2, SSError, MSError]);
|
|
AReport.Add('%10s %10d %10.2f', ['Total', NCases-1, SSTotal]);
|
|
AReport.Add('');
|
|
AReport.Add('');
|
|
end;
|
|
|
|
// Obtain adjusted means
|
|
AReport.Add(DIVIDER_AUTO);
|
|
AReport.Add('');
|
|
AdjustMeans(AReport);
|
|
|
|
// Make comparisons among groups
|
|
if multcomp then
|
|
begin
|
|
MultCompPage.TabVisible := true;
|
|
MultCompare;
|
|
end else
|
|
MultCompPage.TabVisible := false;
|
|
|
|
|
|
// Do regression, eliminating each block to test effects of that term
|
|
AReport.Add(DIVIDER_AUTO);
|
|
AReport.Add('');
|
|
AReport.Add('TEST FOR EACH SOURCE OF VARIANCE - Type III SS');
|
|
AReport.Add('');
|
|
AReport.Add('--------------------------------------------------------------------------');
|
|
AReport.Add(' SOURCE Deg.F. SS MS F Prob>F');
|
|
AReport.Add('--------------------------------------------------------------------------');
|
|
|
|
localReport := TStringList.Create;
|
|
try
|
|
for i := 1 to NoBlocks - 1 do // covariates, fixed effects, interactions
|
|
begin
|
|
count := 0;
|
|
for j := 1 to NoBlocks-1 do
|
|
begin
|
|
if j = i then continue; // exclude the factor to be tested
|
|
for k := 1 to Block[j-1,4] do // no of vectors in block
|
|
begin
|
|
col := Block[j-1,2] + k - 1; // count from beginning col.
|
|
count := count + 1;
|
|
ColNoSelected[count-1] := col;
|
|
IndepIndex[count-1] := count;
|
|
RowLabels[count-1] := OS3MainFrm.DataGrid.Cells[col,0];
|
|
end;
|
|
end; // get next block of vectors for factors to be included
|
|
count := count + 1;
|
|
noind := count - 1;
|
|
ColNoSelected[count-1] := DepColNo;
|
|
IndepIndex[count-1] := count;
|
|
RowLabels[count-1] := OS3MainFrm.DataGrid.Cells[DepColNo,0];
|
|
Correlations(count,ColNoSelected,Cormat,Means,Variances,StdDevs,errorcode,NCases);
|
|
|
|
// Get regression
|
|
SetLength(BStdErrs, noind+1);
|
|
SetLength(BTtests, noind+1);
|
|
localReport.Add(Blocklabel[i-1]);
|
|
localReport.Add('');
|
|
MReg(
|
|
noind, ColNoSelected, DepColNo, RowLabels, Means, Variances, StdDevs,
|
|
BWeights, BetaWeights, BStdErrs, BTtests, tProbs, R2, StdErrEst, NCases,
|
|
errorcode, false, localReport
|
|
);
|
|
localReport.Add('');
|
|
|
|
df1 := Block[i-1,4];
|
|
SSGroups := (FullR2 - R2)* SSTotal;
|
|
SSGrpTot := SSGrpTot + SSGroups;
|
|
MSGroups := SSGroups / df1;
|
|
F := MSGroups / MSError;
|
|
Prob := probf(F,df1,df2);
|
|
|
|
AReport.Add('%10s %10.0f %10.2f %10.2f %10.3g %10.4f', [BlockLabel[i-1], df1, SSGroups, MSGroups, F, Prob]);
|
|
end; // get next Block to eliminate
|
|
|
|
AReport.Add('');
|
|
AReport.Add('----------------------------------------------------------------------');
|
|
AReport.Add('%10s %10.0f %10.2f %10.2f', ['ERROR', df2, SSError, MSError]);
|
|
AReport.Add('----------------------------------------------------------------------');
|
|
AReport.Add('%10s %10d %10.2f', ['TOTAL', NCases-1, SSTotal]);
|
|
|
|
AReport.Add('');
|
|
AReport.AddStrings(localReport);
|
|
finally
|
|
localReport.Free;
|
|
end;
|
|
|
|
{
|
|
df1 := NoCovs;
|
|
SSGroups := SSExplained - SSGrpTot;
|
|
MSGroups := SSGroups / df1;
|
|
F := MSGroups / MSError;
|
|
Prob := probf(F,df1,df2);
|
|
outline := format('%10s %10.0f %10.2f %10.2f %10.3f %10.4f',
|
|
['Covariates',df1,SSGroups,MSGroups,F,Prob]);
|
|
OutputFrm.RichEdit.Lines.Add(outline);
|
|
|
|
outline := format('%10s %10.0f %10.2f %10.2f',
|
|
['Error',df2,SSError,MSError]);
|
|
OutputFrm.RichEdit.Lines.Add(outline);
|
|
outline := format('%10s %10d %10.2f',
|
|
['Total',NCases-1,SSTotal]);
|
|
OutputFrm.RichEdit.Lines.Add(outline);
|
|
OutPutFrm.RichEdit.Lines.Add('');
|
|
}
|
|
tProbs := nil;
|
|
BTTests := nil;
|
|
BStdErrs := nil;
|
|
|
|
{$IFDEF ANCOVA_DEBUG}
|
|
DebugLn('EXIT EntryOpt1');
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TAncovaForm.GenCovInteracts;
|
|
var
|
|
i, j, k, m, vect1col, vect2col, col: integer;
|
|
value: double;
|
|
labelstr, cell1, cell2: string;
|
|
startcol, endcol, novectors, oldnovars: integer;
|
|
lastblock, firstblock: integer;
|
|
begin
|
|
col := NoVariables;
|
|
oldnovars := NoVariables;
|
|
novectors := 0;
|
|
NoTestVecs := 0;
|
|
startcol := Block[NoBlocks-1,3] + 1;
|
|
lastblock := NoBlocks;
|
|
firstblock := NoCovs + 1;
|
|
|
|
// product vectors for each covariate
|
|
for i := 1 to NoCovs do
|
|
begin
|
|
vect1col := Block[i-1,2];
|
|
for j := firstblock to lastblock do
|
|
begin
|
|
for k := 1 to Block[j-1,4] do
|
|
begin
|
|
vect2col := Block[j-1,2] + k - 1; // first vector col. of B
|
|
col := col + 1;
|
|
novectors := novectors + 1;
|
|
NoTestVecs := NoTestVecs + 1;
|
|
|
|
DictionaryFrm.NewVar(col);
|
|
labelstr := OS3MainFrm.DataGrid.Cells[vect1col,0] + 'x';
|
|
labelstr := labelstr + OS3MainFrm.DataGrid.Cells[vect2col,0];
|
|
OS3MainFrm.DataGrid.Cells[col,0] := labelstr;
|
|
DictionaryFrm.DictGrid.Cells[1,col] := labelstr;
|
|
for m := 1 to NoCases do
|
|
begin
|
|
if not GoodRecord(m,NoSelected,ColNoSelected) then Continue;
|
|
cell1 := Trim(OS3MainFrm.DataGrid.Cells[vect1col,m]);
|
|
cell2 := Trim(OS3MainFrm.DataGrid.Cells[vect2col,m]);
|
|
value := StrToFloat(cell1) * StrToFloat(cell2);
|
|
OS3MainFrm.DataGrid.Cells[col,m] := FloatToStr(value);
|
|
end; // next case m
|
|
end; // next l vector
|
|
end; // next fixed effects factor j and interactions
|
|
end; // next covariate i
|
|
|
|
endcol := col; // last grid column containing two-way interaction vectors
|
|
NoBlocks := NoBlocks + 1;
|
|
Block[NoBlocks-1,0] := 0; // zeroes for interactions
|
|
Block[NoBlocks-1,1] := 0; // zeroes for interactions
|
|
Block[NoBlocks-1,2] := startcol; // grid start col for 2-way interactions
|
|
Block[NoBlocks-1,3] := endcol; // grid end col for 2-way interactions
|
|
Block[NoBlocks-1,4] := novectors; // no. of vectors for 2-way interaction
|
|
BlockLabel[NoBlocks-1] := BlockLabel[i-1] + 'xFixed';
|
|
NoVariables := oldnovars + novectors;
|
|
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.AdjustMeans(AReport: TStrings);
|
|
var
|
|
sum : double;
|
|
GrpCovMeans : DblDyneMat = nil;
|
|
AdjMeans : DblDyneVec = nil;
|
|
Intercepts : DblDyneVec = nil;
|
|
i, j, k, col, grp, nogrps : integer;
|
|
value : double;
|
|
Labels : StrDyneVec = nil;
|
|
noingrp : IntDyneVec = nil;
|
|
XValue : DblDyneVec = nil;
|
|
cell1 : string;
|
|
begin
|
|
SetLength(GrpCovMeans,noind,noind);
|
|
SetLength(AdjMeans,noind);
|
|
SetLength(Intercepts,noind);
|
|
SetLength(Labels,noind);
|
|
SetLength(noingrp,noind);
|
|
SetLength(XValue,noind);
|
|
|
|
SetLength(FMeansPlotData, NoFixed, NoCases);
|
|
SetLength(FAdjMeansPlotData, NoFixed, NoCases);
|
|
|
|
FChartCombobox.Parent.Left := 0;
|
|
PopulateChartCombobox;
|
|
// SelectPlot(nil);
|
|
|
|
// Get means for groups and covariates
|
|
for j := 1 to NoFixed do // for each fixed variable
|
|
begin
|
|
nogrps := maxgrp[j-1] - mingrp[j-1] + 1;
|
|
for i := 0 to nogrps-1 do
|
|
begin
|
|
XValue[i] := i+1;
|
|
noingrp[i] := 0;
|
|
for k := 0 to NoCovs-1 do
|
|
begin
|
|
GrpCovMeans[i, k] := 0.0;
|
|
Labels[k] := 'Group ' + IntToStr(k+1);
|
|
end;
|
|
end;
|
|
for i := 0 to nogrps-1 do AdjMeans[i] := 0.0;
|
|
for i := 1 to NoCases do
|
|
begin
|
|
cell1 := Trim(OS3MainFrm.DataGrid.Cells[FixedCols[j-1],i]);
|
|
if cell1 = '' then continue;
|
|
grp := round(StrToFloat(cell1));
|
|
grp := grp - mingrp[j-1];
|
|
noInGrp[grp] := noInGrp[grp] + 1;
|
|
for k := 0 to NoCovs-1 do
|
|
begin
|
|
col := CovCols[k];
|
|
cell1 := Trim(OS3MainFrm.DataGrid.Cells[col,i]);
|
|
if cell1 = '' then continue;
|
|
value := StrToFloat(cell1);
|
|
GrpCovMeans[grp, k] := GrpCovMeans[grp, k] + value;
|
|
end;
|
|
cell1 := Trim(OS3MainFrm.DataGrid.Cells[DepColNo, i]);
|
|
if cell1 = '' then continue;
|
|
value := StrToFloat(cell1);
|
|
AdjMeans[grp] := AdjMeans[grp] + value;
|
|
end; // next case i
|
|
|
|
SetLength(FMeansPlotData[j-1], NoGrps);
|
|
for k := 1 to nogrps do
|
|
begin
|
|
AdjMeans[k-1] := AdjMeans[k-1] / noingrp[k-1];
|
|
FMeansPlotData[j-1, k-1] := AdjMeans[k-1];
|
|
for i := 1 to NoCovs do
|
|
GrpCovMeans[k-1,i-1] := GrpCovMeans[k-1,i-1] / noingrp[k-1];
|
|
end;
|
|
|
|
// print unadjusted means
|
|
AReport.Add('Unadjusted Group Means for Group Variable ' + OS3MainFrm.DataGrid.Cells[FixedCols[j-1] ,0]);
|
|
DynVectorPrint(AdjMeans, nogrps, 'Means', Labels, NCases, AReport);
|
|
|
|
// Get intercepts for group equations for this fixed effect variable
|
|
sum := 0.0;
|
|
for k := 1 to nogrps - 1 do // no. vectors is 1 less than no. groups
|
|
begin
|
|
intercepts[k-1] := constant + BWeights[NoCovs+k-1];
|
|
sum := sum + BWeights[NoCovs+k-1];
|
|
end;
|
|
intercepts[nogrps-1] := constant - sum;
|
|
|
|
// get adjusted means
|
|
SetLength(FAdjMeansPlotData[j-1], noGrps);
|
|
for k := 1 to nogrps do
|
|
begin
|
|
sum := 0.0;
|
|
for i := 1 to NoCovs do
|
|
sum := sum + BWeights[i-1] * (GrpCovMeans[k-1,i-1]-Means[i-1]);
|
|
AdjMeans[k-1] := AdjMeans[k-1] - sum;
|
|
FAdjMeansPlotData[j-1, k-1] := AdjMeans[k-1];
|
|
end;
|
|
|
|
// print results for intercepts
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
AReport.Add('');
|
|
AReport.Add('Intercepts for Each Group Regression Equation for Variable: ' + OS3MainFrm.DataGrid.Cells[FixedCols[j-1] ,0]);
|
|
DynVectorPrint(Intercepts, nogrps, 'Intercepts', Labels, NCases, AReport);
|
|
|
|
// print adjusted means
|
|
AReport.Add(DIVIDER_SMALL_AUTO);
|
|
AReport.Add('');
|
|
AReport.Add('Adjusted Group Means for Group Variable ' + OS3MainFrm.DataGrid.Cells[FixedCols[j-1] ,0]);
|
|
DynVectorPrint(AdjMeans, nogrps, 'Means', Labels, NCases, AReport);
|
|
end;
|
|
|
|
if plot then
|
|
begin
|
|
ChartPage.TabVisible := true;
|
|
SelectPlot(nil);
|
|
end else
|
|
ChartPage.TabVisible := false;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.MultCompare;
|
|
var
|
|
lReport: TStrings;
|
|
i, j, size: integer;
|
|
covmat: DblDyneMat = nil;
|
|
title: string;
|
|
Labels: StrDyneVec = nil;
|
|
sum: double;
|
|
df1, df2, F, Prob: double;
|
|
begin
|
|
SetLength(covmat, noind, noind);
|
|
SetLength(Labels, noind);
|
|
|
|
lReport := TStringList.Create;
|
|
try
|
|
lReport.Add(DIVIDER_SMALL_AUTO);
|
|
lReport.Add('Multiple Comparisons Among Group Means');
|
|
lReport.Add(DIVIDER_SMALL_AUTO);
|
|
lReport.Add('');
|
|
|
|
SVDInverse(IndMat,noind);
|
|
|
|
size := noind - NoCovs;
|
|
title := 'Inverse of Independents Matrix';
|
|
|
|
for i := 0 to noind-1 do
|
|
Labels[i] := 'Group ' + IntToStr(i+1);
|
|
|
|
for i := 0 to noind-NoCovs-1 do
|
|
for j := 0 to noind-NoCovs-1 do
|
|
covmat[i, j] := sqr(StdErrEst) * IndMat[NoCovs+i,NoCovs+j] / (Variances[NoCovs+j] * (NoCases-1));
|
|
|
|
for i := 0 to size do
|
|
Labels[i] := 'Group ' + IntToStr(i+1);
|
|
|
|
// augment matrix
|
|
for i := 0 to size-1 do
|
|
begin
|
|
sum := 0.0;
|
|
for j := 0 to size-1 do
|
|
sum := sum + covmat[i, j];
|
|
covmat[i, size] := -sum;
|
|
covmat[size, i] := -sum;
|
|
end;
|
|
|
|
sum := 0.0;
|
|
for i := 0 to size-1 do
|
|
sum := sum + covmat[i, size];
|
|
|
|
covmat[size,size] := -sum;
|
|
|
|
if PrintInverseMatChk.Checked then
|
|
begin
|
|
title := 'Augmented Covariance Among Group Vectors';
|
|
for i := 0 to size-1 do
|
|
Labels[i] := 'Group ' + IntToStr(i+1);
|
|
MatPrint(covmat, size+1, size+1, title, Labels, Labels, NoCases, lReport);
|
|
lReport.Add(DIVIDER_SMALL_AUTO);
|
|
|
|
end;
|
|
|
|
// Contrast the b coefficients
|
|
// Get last B weight from effect coding as - sum of other B weights
|
|
BWeights[noind] := 0.0;
|
|
for i := 0 to noind-1 do
|
|
BWeights[noind] := BWeights[noind] - BWeights[i];
|
|
for i := 1 to size do
|
|
begin
|
|
for j := i + 1 to size + 1 do
|
|
begin
|
|
df1 := 1.0;
|
|
df2 := NoCases - noind - 1;
|
|
F := sqr(BWeights[NoCovs+i-1] - BWeights[NoCovs+j-1]);
|
|
F := F / (covmat[i-1,i-1] + covmat[j-1,j-1] - (covmat[i-1,j-1] + covmat[j-1,i-1]));
|
|
Prob := probf(F,df1,df2);
|
|
lReport.Add('Comparison of Group %d with Group %d', [i,j]);
|
|
lReport.Add('F: %.3f, probability: %.3f with degrees of freedom %.0f and %.0f', [F, Prob, df1, df2]);
|
|
lReport.Add('');
|
|
end;
|
|
end;
|
|
|
|
FMultCompReportFrame.DisplayReport(lReport);
|
|
finally
|
|
lReport.Free;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.PopulateChartCombobox;
|
|
var
|
|
idx: Integer;
|
|
i: Integer;
|
|
begin
|
|
idx := FChartCombobox.ItemIndex;
|
|
|
|
FChartCombobox.Items.Clear;
|
|
for i := 0 to FixedList.Count-1 do
|
|
begin
|
|
FChartCombobox.Items.Add(Format('%s (unadjusted)', [FixedList.Items[i]]));
|
|
FChartCombobox.Items.Add(Format('%s (adjusted)', [FixedList.Items[i]]));
|
|
end;
|
|
|
|
FChartCombobox.ItemIndex := EnsureRange(idx, 0, FChartCombobox.Items.Count-1);
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.Reset;
|
|
var
|
|
i: integer;
|
|
begin
|
|
inherited;
|
|
|
|
if FMultCompReportFrame <> nil then
|
|
FMultCompReportFrame.Clear;
|
|
if FChartCombobox <> nil then
|
|
FChartCombobox.Items.Clear;
|
|
|
|
DepVar.Clear;
|
|
VarList.Clear;
|
|
for i := 1 to NoVariables do
|
|
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
|
|
CovList.Clear;
|
|
FixedList.Clear;
|
|
NoBlocks := 0;
|
|
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.SelectPlot(Sender: TObject);
|
|
var
|
|
fixedIdx: Integer;
|
|
isAdjusted: Boolean;
|
|
ser: TChartSeries;
|
|
clr: TColor;
|
|
begin
|
|
// The combobox contains unadjusted and adjusted means in alternating order
|
|
// even = unadjusted, odd = adjusted
|
|
fixedIdx := FChartCombobox.ItemIndex div 2;
|
|
isAdjusted := odd(FChartCombobox.ItemIndex);
|
|
clr := DATA_COLORS[fixedIdx mod Length(DATA_COLORS)];
|
|
|
|
FChartFrame.Clear;
|
|
FChartFrame.SetXTitle('Group');
|
|
FChartFrame.SetYTitle('Mean');
|
|
|
|
if isAdjusted then
|
|
begin
|
|
FChartFrame.SetTitle('Unadjusted Means');
|
|
ser := FChartFrame.PlotXY(ptBars, nil, FMeansPlotData[fixedIdx], nil, nil, '', clr);
|
|
end else
|
|
begin
|
|
FChartFrame.SetTitle('Adjusted Means');
|
|
ser := FChartFrame.PlotXY(ptBars, nil, FAdjMeansPlotData[fixedIdx], nil, nil, '', clr);
|
|
end;
|
|
|
|
with TBarSeries(ser) do
|
|
begin
|
|
{$IF LCL_FullVersion >= 2010000}
|
|
DepthBrightnessDelta := -30;
|
|
{$IFEND}
|
|
end;
|
|
|
|
FChartFrame.Chart.BottomAxis.Marks.Source := ser.Source;
|
|
FChartFrame.Chart.BottomAxis.Marks.Style := smsXValue;
|
|
FChartFrame.Chart.Legend.Visible := false;
|
|
|
|
FChartFrame.UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.UpdateBtnStates;
|
|
var
|
|
lSelected: Boolean;
|
|
i: Integer;
|
|
begin
|
|
inherited;
|
|
|
|
if FMultCompReportFrame <> nil then
|
|
FMultCompReportFrame.UpdateBtnStates;
|
|
|
|
DepIn.Enabled := (VarList.ItemIndex > -1) and (DepVar.Text = '');
|
|
DepOut.Enabled := (DepVar.Text <> '');
|
|
|
|
lSelected := false;
|
|
for i := 0 to VarList.Items.Count-1 do
|
|
if VarList.Selected[i] then
|
|
begin
|
|
lSelected := true;
|
|
break;
|
|
end;
|
|
FixedIn.Enabled := lSelected;
|
|
CovIn.Enabled := lSelected;
|
|
|
|
lSelected := false;
|
|
for i := 0 to FixedList.Items.Count-1 do
|
|
if FixedList.Selected[i] then
|
|
begin
|
|
lSelected := true;
|
|
break;
|
|
end;
|
|
FixedOut.Enabled := lSelected;
|
|
|
|
lSelected := false;
|
|
for i := 0 to CovList.Items.Count-1 do
|
|
if CovList.Selected[i] then
|
|
begin
|
|
lSelected := true;
|
|
break;
|
|
end;
|
|
CovOut.Enabled := lSelected;
|
|
end;
|
|
|
|
|
|
function TAncovaForm.Validate(out AMsg: String; out AControl: TWinControl): Boolean;
|
|
begin
|
|
Result := false;
|
|
|
|
if DepVar.Text = '' then
|
|
begin
|
|
AMsg := 'No dependent variable selected.';
|
|
AControl := VarList;
|
|
exit;
|
|
end;
|
|
|
|
if (FixedList.Items.Count <= 0) or (CovList.Items.Count <= 0) then
|
|
begin
|
|
AMsg := 'You must have at least one group variable and one covariate';
|
|
AControl := VarList;
|
|
exit;
|
|
end;
|
|
|
|
Result := true;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.VarListDblClick(Sender: TObject);
|
|
var
|
|
index: Integer;
|
|
s: String;
|
|
begin
|
|
index := VarList.ItemIndex;
|
|
if index > -1 then
|
|
begin
|
|
s := VarList.Items[index];
|
|
if DepVar.Text = '' then
|
|
begin
|
|
DepVar.Text := s;
|
|
VarList.Items.Delete(index);
|
|
UpdateBtnStates;
|
|
end else
|
|
begin
|
|
FixedList.Items.Add(s);
|
|
VarList.Items.Delete(index);
|
|
UpdateBtnStates;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TAncovaForm.VarListSelectionChange(Sender: TObject; User: boolean);
|
|
begin
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
end.
|
|
|