Files
lazarus-ccr/applications/lazstats/source/forms/analysis/comparisons/ancovaunit.pas

1341 lines
44 KiB
ObjectPascal

// Use file "ancova.laz" for testing.
// Y --> Dependent Variable
// Group --> Fixed Factors
// X, Z ---> Covariables
unit ANCOVAUnit;
{$mode objfpc}{$H+}
{.$DEFINE ANCOVA_DEBUG}
interface
uses
{$IFDEF ANCOVA_DEBUG}
LazLogger,
{$ENDIF}
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
StdCtrls, Buttons, ExtCtrls,
MainUnit, OutputUnit, FunctionsLib, GraphLib,
Globals, DataProcs, MatrixLib, DictionaryUnit, ContextHelpUnit;
type
{ TANCOVAfrm }
TANCOVAfrm = class(TForm)
Bevel1: TBevel;
Bevel2: TBevel;
Bevel3: TBevel;
HelpBtn: TButton;
MultCompChk: TCheckBox;
Panel1: TPanel;
Panel2: TPanel;
ResetBtn: TButton;
ComputeBtn: TButton;
CloseBtn: TButton;
PlotMeans: TCheckBox;
PrintInverseMat: TCheckBox;
CorrelationMats: TCheckBox;
DescriptiveStats: TCheckBox;
DepIn: TBitBtn;
DepOut: TBitBtn;
FixedIn: TBitBtn;
FixedOut: TBitBtn;
CovIn: TBitBtn;
CovOut: TBitBtn;
DepVar: TEdit;
GroupBox1: TGroupBox;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
FixedList: TListBox;
Label4: TLabel;
CovList: TListBox;
VarList: TListBox;
procedure ComputeBtnClick(Sender: TObject);
procedure CovInClick(Sender: TObject);
procedure CovOutClick(Sender: TObject);
procedure DepInClick(Sender: TObject);
procedure DepOutClick(Sender: TObject);
procedure FixedInClick(Sender: TObject);
procedure FixedOutClick(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure HelpBtnClick(Sender: TObject);
procedure ResetBtnClick(Sender: TObject);
procedure VarListSelectionChange(Sender: TObject; User: boolean);
private
{ private declarations }
FAutoSized: Boolean;
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;
PrintIt : boolean; // true to print correlations in reg procedure
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(AReport: TStrings);
procedure UpdateBtnStates;
public
{ public declarations }
end;
var
ANCOVAfrm: TANCOVAfrm;
implementation
uses
Math;
{ TANCOVAfrm }
procedure TANCOVAfrm.ResetBtnClick(Sender: TObject);
var
i: integer;
begin
DepVar.Text := '';
VarList.Clear;
CovList.Clear;
FixedList.Clear;
for i := 1 to NoVariables do
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
DescriptiveStats.Checked := false;
CorrelationMats.Checked := false;
PrintInverseMat.Checked := false;
PlotMeans.Checked := false;
NoBlocks := 0;
UpdateBtnStates;
end;
procedure TANCOVAfrm.FormShow(Sender: TObject);
begin
ResetBtnClick(self);
end;
procedure TANCOVAfrm.HelpBtnClick(Sender: TObject);
begin
if ContextHelpForm = nil then
Application.CreateForm(TContextHelpForm, ContextHelpForm);
ContextHelpForm.HelpMessage((Sender as TButton).Tag);
end;
procedure TANCOVAfrm.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 TANCOVAfrm.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 TANCOVAfrm.ComputeBtnClick(Sender: TObject);
var
lReport: TStrings;
begin
if DepVar.Text = '' then
begin
MessageDlg('No dependent variable selected.', mtError, [mbOK], 0);
exit;
end;
NoFixed := FixedList.Items.Count;
NoCovs := CovList.Items.Count;
if (NoFixed <= 0) or (NoCovs <= 0) then
begin
MessageDlg('You must have at least one group variable and one covariate', mtError, [mbOK], 0);
exit;
end;
lReport := TStringList.Create;
try
GetParms;
CodeGroups;
GenInteractions;
GenCovInteracts;
DoRegs(lReport);
DisplayReport(lReport);
finally
CleanUp;
lReport.Free;
end;
end;
procedure TANCOVAfrm.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 TANCOVAfrm.DepOutClick(Sender: TObject);
begin
if DepVar.Text <> '' then
begin
VarList.Items.Add(DepVar.Text);
DepVar.Text := '';
end;
UpdateBtnStates;
end;
procedure TANCOVAfrm.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 TANCOVAfrm.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 TANCOVAfrm.FormActivate(Sender: TObject);
var
w: Integer;
begin
if FAutoSized then
exit;
w := MaxValue([HelpBtn.Width, ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]);
HelpBtn.Constraints.MinWidth := w;
ResetBtn.Constraints.MinWidth := w;
ComputeBtn.Constraints.MinWidth := w;
CloseBtn.Constraints.MinWidth := w;
Constraints.MinWidth := Width;
Constraints.MinHeight := Height;
FAutoSized := true;
end;
procedure TANCOVAfrm.FormCreate(Sender: TObject);
begin
Assert(OS3MainFrm <> nil);
if GraphFrm = nil then
Application.CreateForm(TGraphFrm, GraphFrm);
end;
procedure TANCOVAfrm.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 := PlotMeans.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 TANCOVAfrm.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 TANCOVAfrm.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 TANCOVAfrm.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);
PrintIt := CorrelationMats.Checked;
Testout := false;
Probout := 0.99;
AReport.Add('ANALYSIS OF COVARIANCE USING MULTIPLE REGRESSION');
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 TANCOVAfrm.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 TANCOVAfrm.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;
BTtests: DblDyneVec;
BStdErrs: DblDyneVec; // 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('MODEL FOR TESTING ASSUMPTION OF ZERO INTERACTIONS WITH COVARIATES');
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 CorrelationMats.Checked then
begin
AReport.Add('');
AReport.Add('================================================================================');
// AReport.Add('');
title := 'CORRELATION MATRIX';
MatPrint(Cormat, count, count, title, RowLabels, RowLabels, NCases, AReport);
end;
if DescriptiveStats.Checked then
begin
AReport.Add('');
AReport.Add('================================================================================');
DynVectorPrint(Means, count, 'MEANS', RowLabels, NCases, AReport);
AReport.Add('================================================================================');
DynVectorPrint(Variances, count, 'VARIANCES', RowLabels, NCases, AReport);
AReport.Add('================================================================================');
DynVectorPrint(StdDevs, count, 'STD. DEV.S', RowLabels, NCases, AReport);
AReport.Add('================================================================================');
AReport.Add('');
end;
// Get regression
SetLength(tProbs, count);
printIt := false;
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,
printIt, 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('================================================================================');
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('================================================================================');
AReport.Add('');
AReport.Add('Model for Analysis of Covariance');
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 CorrelationMats.Checked then
begin
AReport.Add('');
Title := 'Correlation Matrix';
MatPrint(Cormat, count, count, title, RowLabels, RowLabels, NCases, AReport);
end;
if DescriptiveStats.Checked then
begin
AReport.Add('');
AReport.Add('================================================================================');
DynVectorPrint(Means, count, 'MEANS', RowLabels, NCases, AReport);
AReport.Add('================================================================================');
DynVectorPrint(Variances, count, 'VARIANCES', RowLabels, NCases, AReport);
AReport.Add('================================================================================');
DynVectorPrint(StdDevs, count, 'STD. DEV.S', RowLabels, NCases, AReport);
AReport.Add('================================================================================');
AReport.Add('');
end;
// Get regression
PrintIt := true;
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('================================================================================');
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('================================================================================');
AReport.Add('');
AReport.Add('Analysis of Variance for the ANCOVA Model');
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('');
end;
// Obtain adjusted means
AdjustMeans(AReport);
// make comparisons among groups
if multcomp then MultCompare(AReport);
// Now do regression, eliminating each block to test effects of that term
PrintIt := false;
AReport.Add('');
AReport.Add('================================================================================');
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 TANCOVAfrm.GenCovInteracts;
var
i, j, l, 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 l := 1 to Block[j-1,4] do
begin
vect2col := Block[j-1,2] + l - 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 TANCOVAfrm.AdjustMeans(AReport: TStrings);
var
sum : double;
GrpCovMeans : DblDyneMat;
AdjMeans : DblDyneVec;
Intercepts : DblDyneVec;
i, j, k, col, grp, nogrps : integer;
value : double;
Labels : StrDyneVec;
noingrp : IntDyneVec;
XValue : DblDyneVec;
maxmean : double;
cell1 : string;
begin
SetLength(GrpCovMeans,noind,noind);
SetLength(AdjMeans,noind);
SetLength(Intercepts,noind);
SetLength(Labels,noind);
SetLength(noingrp,noind);
SetLength(XValue,noind);
// 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;
maxmean := 0.0;
for i := 1 to nogrps do
begin
XValue[i-1] := i;
noingrp[i-1] := 0;
for k := 1 to NoCovs do GrpCovMeans[i-1,k-1] := 0.0;
end;
for i := 1 to nogrps do AdjMeans[i-1] := 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] + 1;
noingrp[grp-1] := noingrp[grp-1] + 1;
for k := 1 to NoCovs do
begin
col := CovCols[k-1];
cell1 := Trim(OS3MainFrm.DataGrid.Cells[col,i]);
if cell1 = '' then continue;
value := StrToFloat(cell1);
GrpCovMeans[grp-1,k-1] := GrpCovMeans[grp-1,k-1] + value;
end;
cell1 := Trim(OS3MainFrm.DataGrid.Cells[DepColNo,i]);
if cell1 = '' then continue;
value := StrToFloat(cell1);
AdjMeans[grp-1] := AdjMeans[grp-1] + value;
end; // next case i
SetLength(GraphFrm.Ypoints,1,nogrps);
SetLength(GraphFrm.Xpoints,1,nogrps);
for k := 1 to nogrps do
begin
AdjMeans[k-1] := AdjMeans[k-1] / noingrp[k-1];
GraphFrm.Ypoints[0,k-1] := AdjMeans[k-1];
GraphFrm.Xpoints[0,k-1] := k;
if AdjMeans[k-1] > maxmean then maxmean := AdjMeans[k-1];
for i := 1 to NoCovs do
begin
GrpCovMeans[k-1,i-1] := GrpCovMeans[k-1,i-1] / noingrp[k-1];
end;
end;
// print unadjusted means
AReport.Add('================================================================================');
AReport.Add('');
AReport.Add('Unadjusted Group Means for Group Variables ' + OS3MainFrm.DataGrid.Cells[FixedCols[j-1] ,0]);
DynVectorPrint(AdjMeans,nogrps,'Means',Labels,NCases, AReport);
AReport.Add('');
// plot group means if requested
if plot then
begin
GraphFrm.nosets := 1;
GraphFrm.nbars := nogrps;
GraphFrm.Heading := 'Unadjusted Means';
GraphFrm.XTitle := 'GROUP';
GraphFrm.YTitle := 'Mean';
GraphFrm.barwideprop := 0.5;
GraphFrm.AutoScaled := false;
GraphFrm.miny := 0.0;
GraphFrm.maxy := maxmean;
GraphFrm.GraphType := 2; // 3d Vertical Bar Chart
GraphFrm.BackColor := clCream;
GraphFrm.WallColor := clDkGray;
GraphFrm.FloorColor := clLtGray;
GraphFrm.ShowBackWall := true;
GraphFrm.ShowModal;
end;
// 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
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;
GraphFrm.Ypoints[0,k-1] := AdjMeans[k-1];
Labels[k-1] := 'Group ' + IntToStr(k);
end;
// plot group means if requested
if plot then
begin
GraphFrm.nosets := 1;
GraphFrm.nbars := nogrps;
GraphFrm.Heading := 'Adjusted Means';
GraphFrm.XTitle := 'GROUP';
GraphFrm.YTitle := 'Mean';
GraphFrm.barwideprop := 0.5;
GraphFrm.AutoScaled := false;
GraphFrm.miny := 0.0;
GraphFrm.maxy := maxmean;
GraphFrm.GraphType := 2; // 3d Vertical Bar Chart
GraphFrm.BackColor := clCream;
GraphFrm.WallColor := clDkGray;
GraphFrm.FloorColor := clLtGray;
GraphFrm.ShowBackWall := true;
GraphFrm.ShowModal;
end;
// print results for intercepts
AReport.Add('================================================================================');
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);
AReport.Add('');
// print adjusted means
AReport.Add('================================================================================');
AReport.Add('');
AReport.Add('Adjusted Group Means for Group Variables ' + OS3MainFrm.DataGrid.Cells[FixedCols[j-1] ,0]);
DynVectorPrint(AdjMeans, nogrps, 'Means', Labels, NCases, AReport);
AReport.Add('');
end;
//OutputFrm.ShowModal;
//OutputFrm.RichEdit.Clear;
XValue := nil;
noingrp := nil;
Labels := nil;
intercepts := nil;
AdjMeans := nil;
GrpCovMeans := nil;
GraphFrm.Xpoints := nil;
GraphFrm.Ypoints := nil;
end;
procedure TANCOVAfrm.MultCompare(AReport: TStrings);
var
i, j, size : integer;
covmat : DblDyneMat;
title : string;
Labels : StrDyneVec;
sum : double;
df1, df2, F, Prob : double;
begin
SetLength(covmat,noind,noind);
SetLength(Labels,noind);
AReport.Add('================================================================================');
AReport.Add('');
AReport.Add('Multiple Comparisons Among Group Means');
AReport.Add('');
SVDInverse(IndMat,noind);
size := noind - NoCovs;
title := 'Inverse of Independents Matrix';
for i := 1 to noind do Labels[i-1] := 'Group ' + IntToStr(i);
for i := 1 to noind-NoCovs do
for j := 1 to noind-NoCovs do
covmat[i-1,j-1] := sqr(StdErrEst) * IndMat[NoCovs+i-1,NoCovs+j-1] /
(Variances[NoCovs+j-1] * (NoCases-1));
for i := 1 to size+1 do Labels[i-1] := 'Group ' + IntToStr(i);
// augment matrix
for i := 1 to size do
begin
sum := 0.0;
for j := 1 to size do
begin
sum := sum + covmat[i-1,j-1];
end;
covmat[i-1,size] := -sum;
covmat[size,i-1] := -sum;
end;
sum := 0.0;
for i := 1 to size do sum := sum + covmat[i-1,size];
covmat[size,size] := -sum;
if PrintInverseMat.Checked then
begin
AReport.Add('================================================================================');
AReport.Add('');
title := 'Augmented Covariance Among Group Vectors';
for i := 1 to size do Labels[i-1] := 'Group ' + IntToStr(i);
MatPrint(covmat,size+1,size+1,title,Labels,Labels,NoCases, AReport);
end;
// Now, 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);
AReport.Add('Comparison of Group %3d with Group %3d', [i,j]);
AReport.Add('F = %10.3f, probability = %5.3f with degrees of freedom %5.0f and %5.0f', [F, Prob, df1, df2]);
end;
end;
AReport.Add('');
Labels := nil;
covmat := nil;
end;
procedure TANCOVAfrm.UpdateBtnStates;
var
lSelected: Boolean;
i: Integer;
begin
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;
procedure TANCOVAfrm.VarListSelectionChange(Sender: TObject; User: boolean);
begin
UpdateBtnStates;
end;
initialization
{$I ancovaunit.lrs}
end.