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

3431 lines
110 KiB
ObjectPascal

// Data file for testing: anova2.laz
// - Row, Col --> Fixed effect independent variables
// - Cov1, Col2 --> Covariates (continuous)
// - X --> Continuouse dependent variables
// - Begin definition of an interaction, click Row, Col, end definition
unit GLMUnit;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
MainUnit, MatrixLib, Globals, OutputUnit, FunctionsLib,
DictionaryUnit, StdCtrls, Buttons, ExtCtrls, ContextHelpUnit;
type
{ TGLMFrm }
TGLMFrm = class(TForm)
Bevel1: TBevel;
Bevel2: TBevel;
Bevel3: TBevel;
HelpBtn: TButton;
Memo2: TLabel;
Panel1: TPanel;
Panel10: TPanel;
Panel11: TPanel;
Panel12: TPanel;
Panel13: TPanel;
Panel14: TPanel;
Panel2: TPanel;
Panel3: TPanel;
Panel4: TPanel;
Panel5: TPanel;
Panel6: TPanel;
Panel7: TPanel;
Panel8: TPanel;
Panel9: TPanel;
ShowDesignChk: TCheckBox;
ContDepInBtn: TBitBtn;
GroupBox2: TGroupBox;
RndIndepOutBtn: TBitBtn;
CovInBtn: TBitBtn;
CovOutBtn: TBitBtn;
ContDepOutBtn: TBitBtn;
CatDepInBtn: TBitBtn;
CatDepOutBtn: TBitBtn;
ReptDepInBtn: TBitBtn;
ReptDepOutBtn: TBitBtn;
FixedIndepInBtn: TBitBtn;
FixedIndepOutBtn: TBitBtn;
RndIndepInBtn: TBitBtn;
ContDepCode: TListBox;
CatDepCode: TListBox;
ReptDepCode: TListBox;
FixedIndepCode: TListBox;
RndIndepCode: TListBox;
CovariateCode: TListBox;
RepTrtCode: TListBox;
ResetBtn: TButton;
ComputeBtn: TButton;
CloseBtn: TButton;
DescChk: TCheckBox;
CorsChk: TCheckBox;
Label12: TLabel;
IndOrderBox: TListBox;
TypeGroup: TRadioGroup;
ResidChk: TCheckBox;
EndDefBtn: TButton;
GroupBox1: TGroupBox;
InterDefList: TListBox;
Label11: TLabel;
InteractList: TListBox;
ShowModelBtn: TButton;
DepContList: TListBox;
ModelEdit: TEdit;
FixedList: TListBox;
Label10: TLabel;
Label6: TLabel;
DepCatList: TListBox;
Label7: TLabel;
Label8: TLabel;
Label9: TLabel;
CovariateList: TListBox;
RepTrtList: TListBox;
RandomList: TListBox;
RepeatList: TListBox;
VarList: TListBox;
StartInterBtn: TButton;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
procedure CatDepInBtnClick(Sender: TObject);
procedure CatDepOutBtnClick(Sender: TObject);
procedure ComputeBtnClick(Sender: TObject);
procedure ContDepCodeSelectionChange(Sender: TObject; User: boolean);
procedure ContDepInBtnClick(Sender: TObject);
procedure ContDepOutBtnClick(Sender: TObject);
procedure CovariateListClick(Sender: TObject);
procedure CovInBtnClick(Sender: TObject);
procedure CovOutBtnClick(Sender: TObject);
procedure EndDefBtnClick(Sender: TObject);
procedure FixedIndepInBtnClick(Sender: TObject);
procedure FixedIndepOutBtnClick(Sender: TObject);
procedure FixedListClick(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure HelpBtnClick(Sender: TObject);
procedure Panel9Resize(Sender: TObject);
procedure RandomListClick(Sender: TObject);
procedure ReptDepInBtnClick(Sender: TObject);
procedure ReptDepOutBtnClick(Sender: TObject);
procedure RepTrtListClick(Sender: TObject);
procedure ResetBtnClick(Sender: TObject);
procedure RndIndepInBtnClick(Sender: TObject);
procedure RndIndepOutBtnClick(Sender: TObject);
procedure ShowModelBtnClick(Sender: TObject);
procedure StartInterBtnClick(Sender: TObject);
private
{ private declarations }
IntDef : boolean;
DefLine : integer; // number of interaction terms - 1
NoInterDefs : integer; // number of interactions in the model
NContDep : integer; // no. of continuous dependent variables
NCatDep : integer; // no. of categorical dependent variables
NReptDep : integer; // no. of repeated dependent variables
NFixedIndep : integer; // no. of fixed effect independent variables
NRndIndep : integer; // no. of random effect independent variables
NCovIndep : integer; // no. of covariate independent variables
model : integer; // 1 if multreg, 2 if canonical
novars : integer; // total no. of vectors in analysis grid
totalobs : integer; // total no. of data grid observations
gencount, oldcount : integer; // no. columns generated in datagrid
ContDepID : IntDyneVec; // grid col. no.s of continuous dependent var.s
CatDepID : IntDyneVec; // grid col. no.s of categorical dependent var.s
ReptDepID : IntDyneVec; // grid col. no.s of repeated dep. variables
FixedIndepID : IntDyneVec; // grid col. no.s of fixed independent var.s
RndIndepID : IntDyneVec; // grid col. no.s of random independent var.s
CovIndepID : IntDyneVec; // grid col. no.s of covariates
DataGrid : DblDyneMat; // array for generated vectors and values
GenLabels : StrDyneVec; // array of labels for data matrix
ContDepPos : IntDyneVec; // datagrid position of continuous variables
CatDepPos : IntDyneVec; // beginning datagrid position of categorical var. vectors
ReptDepPos : IntDyneVec; // datagrid position of repeated variable
ReptIndepPos : IntDyneVec; // datagrid pos. of subject vectors
ReptTrtPos : IntDyneVec; // datagrid pos. of repeated treatment vectors
FixedIndepPos : IntDyneVec; // datagrid position of first vector for cat indep. var.
RndIndepPos : IntDyneVec; // datagrid position of first vector for rnd. indep. var.
CovIndepPos : IntDyneVec; // datagrid positions of covariates
InteractPos : IntDyneVec; // datagrid positions of interactions
Labels : StrDyneVec; // labels for the analyses
ColSelected : IntDyneVec; // datagrid columns of variables in the analysis
NFixVecIndep : IntDyneVec; // no. of vectors for fixed independent vars.
NRndVecIndep : IntDyneVec; // no. of vectors for random indep. vars.
NFixVecDep : IntDyneVec; // no. of vectors for fixed dependent vars.
NInteractVecs : IntDyneVec; // no. of vectors for each interaction
OldR2 : double; // Previously obtained R^2 for stepwise addition
R2 : double; // Squared mult. R obtained from RegAnal
rmatrix : DblDyneMat; // correlation matrix
indmatrix : DblDyneMat; // correlations among independent variable
rxy : DblDyneVec; // correlations between dependent and independent var.s
invmatrix : DblDyneMat; // inverse of independent correlations
means : DblDyneVec; // means of variables
Vars : DblDyneVec; // variances of variables
StdDevs : DblDyneVec; // standard deviations of variables
B : DblDyneVec; // raw regression coefficients
Beta : DblDyneVec; // standardized regression coefficients
workmat : DblDyneMat; // work matrix for inverse referenced at 1 (not zero)
TypeISS : DblDyneVec; // Incremental SS
TypeIISS : DblDyneVec; // Unique SS
TypeIMS : DblDyneVec; // Incremental SS
TypeIIMS : DblDyneVec; // Unique MS
TypeIDF1 : DblDyneVec; // numerator d.f. for incremental ms
TypeIIDF1 : DblDyneVec; // numerator d.f. for unique ms
TypeIDF2 : DblDyneVec; // denominator d.f. for incremental ms
TypeIIDF2 : DblDyneVec; // denominator d.f. for unique ms
TypeIF : DblDyneVec; // F for incremental ms
TypeIProb : DblDyneVec; // Probability of F for incremental ms
TypeIIF : DblDyneVec; // F for unique MS
TypeIIProb : DblDyneVec; // Probability for unique ms
procedure AllocateIDMem;
procedure GetIDs;
function GetVarCount : integer;
procedure AllocateGridMem;
procedure DeallocateGridMem;
procedure DeallocateIDMem;
procedure DummyCodes(min, max: integer; const CodePattern: IntDyneMat);
procedure EffectCodes(min, max: integer; const CodePattern: IntDyneMat);
procedure OrthogCodes(min, max: integer; const CodePattern: IntDyneMat);
procedure RegAnal(Nentered: integer; AReport: TStrings);
procedure PartIEntry;
procedure PartIIEntry;
procedure ModelIAnalysis(AReport: TStrings);
procedure ModelIIAnalysis(AReport: TStrings);
procedure ModelIIIAnalysis(AReport: TStrings);
function CntIntActVecs(linestr : string) : integer;
procedure GenInterVecs(linestr : string);
procedure CanCor(NLeft : integer; NRight : integer; GridPlace : IntDyneVec; AReport: TStrings);
procedure UpdateBtnStates;
public
{ public declarations }
end;
var
GLMFrm: TGLMFrm;
implementation
uses
Math,
Utils;
{ TGLMFrm }
procedure TGLMFrm.ResetBtnClick(Sender: TObject);
VAR i : integer;
begin
VarList.Items.Clear;
DepCatList.Items.Clear;
DepContList.Items.Clear;
RepeatList.Items.Clear;
RepTrtList.Items.Clear;
RepTrtCode.Items.Clear;
FixedList.Items.Clear;
RandomList.Items.Clear;
CovariateList.Items.Clear;
InterDefList.Items.Clear;
InteractList.Items.Clear;
ContDepCode.Items.Clear;
CatDepCode.Items.Clear;
ReptDepCode.Items.Clear;
FixedIndepCode.Items.Clear;
RndIndepCode.Items.Clear;
CovariateCode.Items.Clear;
IndOrderBox.Items.Clear;
ModelEdit.Text := '';
NContDep := 0;
NCatDep := 0;
NReptDep := 0;
NFixedIndep := 0;
NRndIndep := 0;
NCovIndep := 0;
DescChk.Checked := false;
CorsChk.Checked := false;
ResidChk.Checked := false;
TypeGroup.ItemIndex := 0;
ContDepOutBtn.Enabled := false;
CatDepOutBtn.Enabled := false;
ReptDepOutBtn.Enabled := false;
FixedIndepOutBtn.Enabled := false;
RndIndepOutBtn.Enabled := false;
CovOutBtn.Enabled := false;
IntDef := false;
DefLine := 0;
NoInterDefs := 0;
for i := 1 to NoVariables do VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
end;
procedure TGLMFrm.RndIndepInBtnClick(Sender: TObject);
var
i: integer;
codestr: string;
begin
i := 0;
while i < VarList.Items.Count do
begin
if VarList.Selected[i] then
begin
RandomList.Items.Add(VarList.Items[i]);
VarList.Items.Delete(i);
NRndIndep := NRndIndep + 1;
codestr := Format('IR%d', [NRndIndep]);
RndIndepCode.Items.Add(codestr);
IndOrderBox.Items.Add(codestr);
i := 0;
end
else
i := i + 1;
end;
UpdateBtnStates;
end;
(*
var
index: integer;
codestr: string;
begin
index := VarList.ItemIndex;
if index > -1 then
begin
RandomList.Items.Add(VarList.Items[index]);
VarList.Items.Delete(index);
NRndIndep := NRndIndep + 1;
codestr := format('IR%d',[NRndIndep]);
RndIndepCode.Items.Add(codestr);
IndOrderBox.Items.Add(codestr);
end;
end;
*)
procedure TGLMFrm.RndIndepOutBtnClick(Sender: TObject);
var
i, index: integer;
cellstring: string;
begin
index := RandomList.ItemIndex;
if index > -1 then
begin
VarList.Items.Add(RandomList.Items[index]);
RandomList.Items.Delete(index);
cellstring := RndIndepCode.Items[index];
RndIndepCode.Items.Delete(index);
for i := IndOrderBox.Items.Count - 1 downto 0 do
if cellstring = IndOrderBox.Items.Strings[i] then
IndOrderBox.Items.Delete(i);
NRndIndep := NRndIndep - 1;
end;
UpdateBtnStates;
end;
procedure TGLMFrm.ShowModelBtnClick(Sender: TObject);
var
i : integer;
codestr : string;
begin
// add all dependent variable codes
if NContDep > 0 then
begin
for i := 0 to NContDep - 1 do
begin
ModelEdit.Text := ModelEdit.Text + ContDepCode.Items.Strings[i];
if i < NContDep - 1 then ModelEdit.Text := ModelEdit.Text + ' + ';
end;
end;
if NCatDep > 0 then
begin
if ModelEdit.Text <> '' then ModelEdit.Text := ModelEdit.Text + ' + ';
for i := 0 to NCatDep - 1 do
begin
ModelEdit.Text := ModelEdit.Text + CatDepCode.Items.Strings[i];
if i < NCatDep - 1 then ModelEdit.Text := ModelEdit.Text + ' + ';
end;
end;
if NReptDep > 0 then
begin
if ModelEdit.Text <> '' then ModelEdit.Text := ModelEdit.Text + ' + ';
ModelEdit.Text := ModelEdit.Text + 'Rep';
end;
// now add the independent variable codes
ModelEdit.Text := ModelEdit.Text + ' = ';
if NFixedIndep > 0 then
begin
for i := 0 to NFixedIndep - 1 do
begin
ModelEdit.Text := ModelEdit.Text + FixedIndepCode.Items.Strings[i];
if i < NFixedIndep - 1 then
ModelEdit.Text := ModelEdit.Text + ' + ';
end;
end;
if NRndIndep > 0 then
begin
if NFixedIndep > 0 then ModelEdit.Text := ModelEdit.Text + ' + ';
for i := 0 to NRndIndep - 1 do
begin
ModelEdit.Text := ModelEdit.Text + RndIndepCode.Items.Strings[i];
if i < NRndIndep - 1 then
ModelEdit.Text := ModelEdit.Text + ' + ';
end;
end;
if NCovIndep > 0 then
begin
if (NFixedIndep > 0) or (NRndIndep > 0) then
ModelEdit.Text := ModelEdit.Text + ' + ';
for i := 0 to NCovIndep - 1 do
begin
ModelEdit.Text := ModelEdit.Text + CovariateCode.Items.Strings[i];
if i < NCovIndep - 1 then
ModelEdit.Text := ModelEdit.Text + ' + ';
end;
end;
// now add interactions
if NoInterDefs > 0 then
begin
ModelEdit.Text := ModelEdit.Text + ' + ';
for i := 0 to NoInterDefs - 1 do
begin
ModelEdit.Text := ModelEdit.Text + InterActList.Items.Strings[i];
if i < NoInterDefs - 1 then
ModelEdit.Text := ModelEdit.Text + ' + ';
end;
end;
// Now add person vectors
if NReptDep > 0 then
begin
ModelEdit.Text := ModelEdit.Text + ' + ';
for i := 0 to NReptDep - 1 do
begin
codestr := format('IP%d',[i+1]);
ModelEdit.Text := ModelEdit.Text + codestr;
if i < NReptDep - 1 then
ModelEdit.Text := ModelEdit.Text + ' + ';
end;
end;
// Now add repeated treatments
if NReptDep > 0 then
begin
ModelEdit.Text := ModelEdit.Text + ' + ';
for i := 0 to NReptDep - 1 do
begin
codestr := format('IR%d',[i+1]);
ModelEdit.Text := ModelEdit.Text + codestr;
if i < NReptDep - 1 then
ModelEdit.Text := ModelEdit.Text + ' + ';
end;
end;
end;
procedure TGLMFrm.StartInterBtnClick(Sender: TObject);
begin
IntDef := true;
end;
procedure TGLMFrm.FormActivate(Sender: TObject);
var
w: Integer;
begin
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;
end;
procedure TGLMFrm.FormCreate(Sender: TObject);
begin
Assert(OS3MainFrm <> nil);
if DictionaryFrm = nil then
Application.CreateForm(TDictionaryFrm, DictionaryFrm);
end;
procedure TGLMFrm.FormShow(Sender: TObject);
begin
ResetBtnClick(self);
end;
procedure TGLMFrm.HelpBtnClick(Sender: TObject);
begin
if ContextHelpForm = nil then
Application.CreateForm(TContextHelpForm, ContextHelpForm);
ContextHelpForm.HelpMessage((Sender as TButton).Tag);
end;
procedure TGLMFrm.RandomListClick(Sender: TObject);
VAR index : integer;
begin
if IntDef then
begin
index := RandomList.ItemIndex;
InterDefList.Items.Add(RndIndepCode.Items.Strings[index]);
DefLine := DefLine + 1; // counter for number of terms - 1
end;
end;
procedure TGLMFrm.ReptDepInBtnClick(Sender: TObject);
var
i: integer;
codestr: string;
begin
i := 0;
while i < VarList.Items.Count do
begin
if VarList.Selected[i] then
begin
RepeatList.Items.Add(VarList.Items[i]);
VarList.Items.Delete(i);
NReptDep := NReptDep + 1;
codestr := Format('DR%d', [NReptDep]);
if NReptDep = 1 then
begin
ReptDepCode.Items.Add(codestr);
codestr := Format('IP%d', [NReptDep]);
IndOrderBox.Items.Add(codestr);
codestr := Format('IR%d', [NReptDep]);
IndOrderBox.Items.Add(codestr);
RepTrtCode.Items.Add(codestr);
codestr := Format('Rep.Trt.%d', [NReptDep]);
RepTrtList.Items.Add(codestr);
end;
i := 0;
end
else
i := i + 1;
end;
UpdateBtnStates;
end;
procedure TGLMFrm.ReptDepOutBtnClick(Sender: TObject);
var
index: integer;
begin
index := RepeatList.ItemIndex;
if index > -1 then
begin
VarList.Items.Add(RepeatList.Items[index]);
RepeatList.Items.Delete(index);
ReptDepCode.Items.Delete(index);
NReptDep := NReptDep - 1;
end;
UpdateBtnStates;
end;
procedure TGLMFrm.RepTrtListClick(Sender: TObject);
VAR index : integer;
begin
if IntDef then
begin
index := RepTrtList.ItemIndex;
InterDefList.Items.Add(RepTrtCode.Items.Strings[index]);
DefLine := DefLine + 1; // counter for number of terms
end;
end;
procedure TGLMFrm.ContDepInBtnClick(Sender: TObject);
var
index: integer;
codestr: string;
begin
index := VarList.ItemIndex;
if index > -1 then
begin
DepContList.Items.Add(VarList.Items[index]);
VarList.Items.Delete(index);
NContDep := NContDep + 1;
codestr := Format('DC%d',[NContDep]);
ContDepCode.Items.Add(codestr);
end;
UpdateBtnStates;
end;
procedure TGLMFrm.ContDepOutBtnClick(Sender: TObject);
var
index: integer;
begin
index := DepContList.ItemIndex;
if index > -1 then
begin
VarList.Items.Add(DepContList.Items[index]);
DepContList.Items.Delete(index);
ContDepCode.Items.Delete(index);
NContDep := NContDep - 1;
end;
UpdateBtnStates;
end;
procedure TGLMFrm.CatDepInBtnClick(Sender: TObject);
var
index: integer;
codestr: string;
begin
index := VarList.ItemIndex;
if index > -1 then
begin
DepCatList.Items.Add(VarList.Items[index]);
VarList.Items.Delete(index);
NCatDep := NCatDep + 1;
codestr := format('DF%d',[NCatDep]);
CatDepCode.Items.Add(codestr);
end;
UpdateBtnStates;
end;
procedure TGLMFrm.CatDepOutBtnClick(Sender: TObject);
var
index: integer;
begin
index := DepCatList.ItemIndex;
if index > -1 then
begin
VarList.Items.Add(DepCatList.Items[index]);
DepCatList.Items.Delete(index);
CatDepCode.Items.Delete(index);
NCatDep := NCatDep - 1;
end;
UpdateBtnStates;
end;
procedure TGLMFrm.ComputeBtnClick(Sender: TObject);
var
i, j: integer; // no. of variables in the analysis
cellstring: string;
lReport: TStrings;
begin
if (NContDep = 0) and (NCatDep = 0) and (NReptDep = 0) then
begin
ErrorMsg('No variables selected.');
exit;
end;
if (NContDep > 0) and (NReptDep > 0) then
begin
ErrorMsg('One cannot have both continuous and repeated dependent variables!');
exit;
end;
gencount := 0; // counter for generated variables
totalobs := 0; // initialize total no. of observations in data grid
AllocateIDMem; // get heap space for arrays
GetIDs; // get var. no.s of dependent and independent variables
novars := GetVarCount; // get total no. of variables to generate
AllocateGridMem; // create data array for values and codes
// Note, the Data Grid first subscript is row (subject) and second the var.
if (NCatDep > 0) or (NContDep > 1) then
model := 2
else
model := 1; // use mult.reg for model 1, canonical reg. for model 2
if NReptDep > 0 then
model := 3;
// This procedure first creates the vectors of dependent variables then the
// vectors for independent variables. A case no. is placed in the first
// column of a data grid followed by the dependent variables and then the
// independent variables. If multiple dependent variables are created, the
// type of analysis is a canonical correlation analysis, otherwise a
// multiple regression analysis. Analyses are performed to obtain both
// Type I SS's and Type II SS's (stepwise addition and unique contribution)
// PART I. ENTRY OF DEPENDENT VARIABLES (AND OBSERVATION NO.)
// Place case labels in data grid and for repeated measures, spread out
// the repeated measures over NoCases * No. repeated measures
PartIEntry;
// PART II. CREATION OF INDEPENDENT VARIABLE VECTORS
// First, if there are repeated measures, generate (n - 1) person vectors
PartIIEntry;
lReport := TStringList.Create;
try
// Now, do the analyses
case model of
1: ModelIAnalysis(lReport); // models with 1 dependent variable
2: ModelIIAnalysis(lReport); // models with 2 or more dependent var.s
3: ModelIIIAnalysis(lReport); // Repeated measures designs
end;
// Place generated data into the main form's grid
if ShowDesignChk.Checked then
begin
if NoVariables < gencount then
begin
j := NoVariables;
for i := j+1 to gencount do
DictionaryFrm.NewVar(j);
end;
OS3MainFrm.DataGrid.RowCount := totalobs+1;
for i := 1 to totalobs do
for j := 1 to gencount do
OS3MainFrm.DataGrid.Cells[j,i] := FloatToStr(DataGrid[i-1,j-1]);
for i := 1 to gencount do
begin
OS3MainFrm.DataGrid.Cells[i,0] := GenLabels[i-1];
DictionaryFrm.Defaults(Self,i);
DictionaryFrm.DictGrid.Cells[1,i] := GenLabels[i-1];
end;
for i := 1 to totalobs do
begin
cellstring := format('CASE%d',[i]);
OS3MainFrm.DataGrid.Cells[0,i] := cellstring;
end;
OS3MainFrm.NoCasesEdit.Text := IntToStr(totalobs);
OS3MainFrm.NoVarsEdit.Text := IntToStr(gencount);
NoVariables := gencount;
NoCases := totalobs;
OS3MainFrm.FileNameEdit.Text := '';
end;
DisplayReport(lReport);
finally
lReport.Free;
DeallocateGridMem; // free up heap allocated to data array
DeallocateIDMem; // free up heap space
end;
end;
procedure TGLMFrm.ContDepCodeSelectionChange(Sender: TObject; User: boolean);
begin
UpdateBtnStates;
end;
procedure TGLMFrm.CovariateListClick(Sender: TObject);
var
index: integer;
begin
if IntDef then
begin
index := CovariateList.ItemIndex;
if index > -1 then
begin
InterDefList.Items.Add(CovariateCode.Items[index]);
DefLine := DefLine + 1; // counter for number of terms - 1
end;
end;
end;
procedure TGLMFrm.CovInBtnClick(Sender: TObject);
var
i: integer;
codestr: string;
begin
i := 0;
while i < VarList.Items.Count do
begin
if VarList.Selected[i] then
begin
CovariateList.Items.Add(VarList.Items[i]);
VarList.Items.Delete(i);
NCovIndep := NCovIndep + 1;
codestr := Format('IC%d', [NCovIndep]);
CovariateCode.Items.Add(codestr);
IndOrderBox.Items.Add(codestr);
i := 0;
end
else
i := i + 1;
end;
UpdateBtnStates;
end;
{
var
index: integer;
codestr: string;
begin
index := VarList.ItemIndex;
if index > -1 then
begin
CovariateList.Items.Add(VarList.Items[index]);
VarList.Items.Delete(index);
NCovIndep := NCovIndep + 1;
codestr := Format('IC%d', [NCovIndep]);
CovariateCode.Items.Add(codestr);
IndOrderBox.Items.Add(codestr);
end;
UpdateBtnStates;
end;
}
procedure TGLMFrm.CovOutBtnClick(Sender: TObject);
var
i, index: integer;
cellstring: string;
begin
index := CovariateList.ItemIndex;
if index > -1 then
begin
VarList.Items.Add(CovariateList.Items[index]);
CovariateList.Items.Delete(index);
cellstring := CovariateCode.Items[index];
CovariateCode.Items.Delete(index);
for i := IndOrderBox.Items.Count - 1 downto 0 do
if cellstring = IndOrderBox.Items[i] then
IndOrderBox.Items.Delete(i);
NCovIndep := NCovIndep - 1;
end;
UpdateBtnStates;
end;
procedure TGLMFrm.EndDefBtnClick(Sender: TObject);
var
index: integer;
nolines: integer;
LineStr: string;
begin
LineStr := '';
nolines := InterDefList.Items.Count;
if nolines > 0 then
begin
for index := 0 to nolines - 1 do
begin
LineStr := LineStr + InterDefList.Items.Strings[index];
if index < nolines - 1 then LineStr := LineStr + ' * ';
end;
InteractList.Items.Add(LineStr);
IndOrderBox.Items.Add(LineStr);
NoInterDefs := NoInterDefs + 1;
end;
InterDefList.Clear;
end;
procedure TGLMFrm.FixedIndepInBtnClick(Sender: TObject);
var
i: integer;
codestr: string;
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);
NFixedIndep := NFixedIndep + 1;
codestr := Format('IF%d', [NFixedIndep]);
FixedIndepCode.Items.Add(codestr);
IndOrderBox.Items.Add(codestr);
i := 0;
end
else
i := i + 1;
end;
UpdateBtnStates;
end;
procedure TGLMFrm.FixedIndepOutBtnClick(Sender: TObject);
var
i, index: integer;
cellstring: string;
begin
index := FixedList.ItemIndex;
if index > -1 then
begin
VarList.Items.Add(FixedList.Items[index]);
FixedList.Items.Delete(index);
cellstring := FixedIndepCode.Items[index];
FixedIndepCode.Items.Delete(index);
NFixedIndep := NFixedIndep - 1;
for i := IndOrderBox.Items.Count - 1 downto 0 do
if IndOrderBox.Items.Strings[i] = cellstring then
IndOrderBox.Items.Delete(i);
end;
UpdateBtnStates;
end;
procedure TGLMFrm.FixedListClick(Sender: TObject);
var
index: integer;
begin
if IntDef then
begin
index := FixedList.ItemIndex;
if index > -1 then begin
InterDefList.Items.Add(FixedIndepCode.Items[index]);
DefLine := DefLine + 1; // counter for number of terms
end;
end;
end;
procedure TGLMFrm.AllocateIDMem;
begin
if NContDep > 0 then
begin
SetLength(ContDepID, NContDep);
SetLength(ContDepPos, NContDep);
end;
if NCatDep > 0 then
begin
SetLength(CatDepID, NCatDep);
SetLength(CatDepPos, NCatDep);
SetLength(NFixVecDep, NCatDep);
end;
if NReptDep > 0 then
begin
SetLength(ReptDepID, NReptDep);
SetLength(ReptDepPos, NReptDep);
SetLength(ReptIndepPos, NoCases);
SetLength(ReptTrtPos, NReptDep);
end;
if NFixedIndep > 0 then
begin
SetLength(FixedIndepID, NFixedIndep);
SetLength(FixedIndepPos, NFixedIndep);
SetLength(NFixVecIndep, NFixedIndep);
end;
if NRndIndep > 0 then
begin
SetLength(RndIndepID, NRndIndep);
SetLength(RndIndepPos, NRndIndep);
SetLength(NRndVecIndep, NRndIndep);
end;
if NCovIndep > 0 then
begin
SetLength(CovIndepID, NCovIndep);
SetLength(CovIndepPos, NCovIndep);
end;
if NoInterDefs > 0 then
begin
SetLength(NInteractVecs, NoInterDefs);
SetLength(InteractPos, NoInterDefs);
end;
end;
procedure TGLMFrm.GetIDs;
var
cellstring: string;
i, j: integer;
begin
if NContDep > 0 then
begin
for i := 0 to NContDep - 1 do
begin
cellstring := DepContList.Items[i];
for j := 1 to NoVariables do
if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then
ContDepID[i] := j;
end;
end;
if NCatDep > 0 then
begin
for i := 0 to NCatDep - 1 do
begin
cellstring := DepCatList.Items[i];
for j := 1 to NoVariables do
if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then
CatDepID[i] := j;
end;
end;
if NReptDep > 0 then
begin
for i := 0 to NReptDep - 1 do
begin
cellstring := RepeatList.Items[i];
for j := 1 to NoVariables do
if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then
ReptDepID[i] := j;
end;
end;
if NFixedIndep > 0 then
begin
for i := 0 to NFixedIndep - 1 do
begin
cellstring := FixedList.Items[i];
for j := 1 to NoVariables do
if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then
FixedIndepID[i] := j;
end;
end;
if NRndIndep > 0 then
begin
for i := 0 to NRndIndep - 1 do
begin
cellstring := RandomList.Items[i];
for j := 1 to NoVariables do
if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then
RndIndepID[i] := j;
end;
end;
if NCovIndep > 0 then
begin
for i := 0 to NCovIndep - 1 do
begin
cellstring := CovariateList.Items[i];
for j := 1 to NoVariables do
if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then
CovIndepID[i] := j;
end;
end;
end;
function TGLMFrm.GetVarCount: integer;
var
count, i, j, col, nvectors: integer;
min, max: integer; // use to get no. of coding vectors for categorical var.s
group: integer;
linestr: string;
begin
count := 1; // one column for case id's
count := count + NContDep + NCovIndep; // sum of continuous variables
if NReptDep > 0 then count := count + 1; // one col. for repeated dep. measure
// plus person vectors for repeated measures (independent predictors)
if NReptDep > 0 then count := count + (NoCases - 1); // person vectors
if NReptDep > 0 then count := count + (NreptDep - 1); // repeated treatment vectors
// calculate min and max for each var. to get no. of vectors
if NCatDep > 0 then
begin
for i := 0 to NCatDep - 1 do
begin
col := CatDepID[i];
min := round(StrToFloat(OS3MainFrm.DataGrid.Cells[col,1]));
max := min;
for j := 1 to NoCases do
begin
group := round(StrToFLoat(OS3MainFrm.DataGrid.Cells[col,j]));
if group < min then min := group;
if group > max then max := group;
end;
count := count + (max - min); // 1 less than the no. of groups
NFixVecDep[i] := count;
end;
end;
// add no. of vectors to count
if NFixedIndep > 0 then
begin
for i := 0 to NFixedIndep - 1 do
begin
col := FixedIndepID[i];
min := round(StrToFloat(OS3MainFrm.DataGrid.Cells[col,1]));
max := min;
for j := 1 to NoCases do
begin
group := round(StrToFloat(OS3MainFrm.DataGrid.Cells[col,j]));
if group < min then min := group;
if group > max then max := group;
end;
count := count + (max - min); // 1 less than the no. of groups
NFixVecIndep[i] := max - min;
end;
end;
// add no. of vectors to count
if NRndIndep > 0 then
begin
for i := 0 to NRndIndep - 1 do
begin
col := RndIndepID[i];
min := round(StrToFloat(OS3MainFrm.DataGrid.Cells[col,1]));
max := min;
for j := 1 to NoCases do
begin
group := round(StrToFloat(OS3MainFrm.DataGrid.Cells[col,j]));
if group < min then min := group;
if group > max then max := group;
end;
count := count + (max - min); // 1 less than the no. of groups
NRndVecIndep[i] := max - min;
end;
end;
// get no. of vectors for each interaction
if NoInterDefs > 0 then
begin
for i := 0 to NoInterDefs - 1 do
begin
linestr := InterActList.Items.Strings[i];
// parse the line for variable definitions and get no. of columns
// and vectors for the products of these variables
nvectors := CntIntActVecs(linestr);
NInteractVecs[i] := nvectors;
count := count + nvectors;
end;
end;
Result := count;
end;
procedure TGLMFrm.AllocateGridMem;
var
norows: integer;
begin
if NReptDep > 0 then
norows := NoCases * NReptDep
else
norows := NoCases;
SetLength(DataGrid, norows+1, novars+4); // grid data for generated data
SetLength(GenLabels, novars+4); // column labels of new data grid
SetLength(Labels, novars+4); // labels of variables entered into analysis
SetLength(ColSelected, novars+4); // datagrid columns selected for analysis
end;
procedure TGLMFrm.DeallocateGridMem;
begin
ColSelected := nil;
Labels := nil;
GenLabels := nil;
DataGrid := nil;
end;
procedure TGLMFrm.DeallocateIDMem;
begin
InteractPos := nil;
NInteractVecs := nil;
CovIndepPos := nil;
CovIndepID := nil;
NRndVecIndep := nil;
RndIndepPos := nil;
RndIndepID := nil;
NFixVecIndep := nil;
FixedIndepPos := nil;
FixedIndepID := nil;
ReptTrtPos := nil;
ReptIndepPos := nil;
ReptDepPos := nil;
ReptDepID := nil;
NFixVecDep := nil;
CatDepPos := nil;
CatDepID := nil;
ContDepPos := nil;
ContDepID := nil;
end;
procedure TGLMFrm.DummyCodes(min, max: integer; const CodePattern: IntDyneMat);
var
ngrps: integer;
vects: integer;
i, j: integer;
begin
ngrps := max - min + 1;
vects := ngrps - 1;
for j := 1 to vects do
for i := 1 to ngrps do
if i = j then CodePattern[i,j] := 1 else CodePattern[i,j] := 0;
end;
procedure TGLMFrm.EffectCodes(min, max: integer; const CodePattern: IntDyneMat);
var
ngrps: integer;
vects: integer;
i, j: integer;
begin
ngrps := max - min + 1;
vects := ngrps - 1;
for i := 1 to ngrps do
for j := 1 to vects do
begin
if i = j then CodePattern[i,j] := 1;
if i = ngrps then CodePattern[i,j] := -1;
if (i <> j) and (i <> ngrps) then CodePattern[i,j] := 0;
end;
end;
procedure TGLMFrm.OrthogCodes(min, max: integer; const CodePattern: IntDyneMat);
var
ngrps: integer;
vects: integer;
i, j: integer;
begin
ngrps := max - min + 1;
vects := ngrps - 1;
for i := 1 to ngrps do
for j := 1 to vects do
begin
if i <= j then CodePattern[i,j] := 1;
if i-1 = j then CodePattern[i,j] := -j;
if i > j+1 then CodePattern[i,j] := 0;
end;
end;
procedure TGLMFrm.Panel9Resize(Sender: TObject);
begin
Bevel3.Constraints.MinHeight := Panel8.Height;
end;
procedure TGLMFrm.RegAnal(Nentered: integer; AReport: TStrings);
var
i, j, nvars, ncases: integer;
title: string;
begin
nvars := Nentered;
ncases := totalobs;
SetLength(rmatrix, nvars+1, nvars+1);
SetLength(indmatrix, nvars-1, nvars-1);
SetLength(rxy, nvars);
SetLength(invmatrix, nvars ,nvars);
SetLength(B, nvars);
SetLength(Beta, nvars);
SetLength(means, nvars);
SetLength(Vars, nvars);
SetLength(StdDevs, nvars);
SetLength(workmat, nvars, nvars);
DynCorrelations(nvars, ColSelected, DataGrid, rmatrix, means, vars, StdDevs, ncases, 3);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
if DescChk.Checked then
begin
title := 'Means';
DynVectorPrint(means, Nentered, title, Labels, ncases, AReport);
end;
if CorsChk.Checked then
begin
title := 'Correlations';
MatPrint(rmatrix, Nentered, Nentered, title, Labels, Labels, ncases, AReport);
end;
for i := 1 to nvars - 1 do
begin
rxy[i-1] := rmatrix[i,0]; // r's with dependent var
for j := 1 to nvars - 1 do
begin
indmatrix[i-1,j-1] := rmatrix[i,j]; // intercorr.s of indep. var.s
workmat[i-1,j-1] := rmatrix[i,j]; // used to get inverse
end;
end;
SVDinverse(workmat, nvars-1);
// Copy inverse to zero indexed matrix
for i := 1 to nvars-1 do
for j := 1 to nvars-1 do
invmatrix[i-1,j-1] := workmat[i-1,j-1];
title := 'inverse of indep. matrix';
// get betas and squared multiple correlation
R2 := 0.0;
for i := 1 to nvars-1 do
begin
Beta[i-1] := 0.0;
for j := 1 to nvars-1 do
Beta[i-1] := Beta[i-1] + invmatrix[i-1,j-1] * rxy[j-1];
R2 := R2 + Beta[i-1] * rxy[i-1];
end;
// outline := format('Squared Multiple Correlation = %6.4f',[R2]);
// OutputFrm.RichEdit.Lines.Add(outline);
// title := 'Standardized regression coefficients';
// DynVectorPrint(Beta,Nentered-1,title,Labels,ncases);
// get raw coefficients
for i := 1 to nvars - 1 do
begin
if StdDevs[i] > 0.0 then
B[i-1] := Beta[i-1] * (StdDevs[0] / StdDevs[i])
else
B[i-1] := 0.0;
end;
// title := 'Raw regression coefficients';
// DynVectorPrint(B,Nentered-1,title,Labels,ncases);
// OutputFrm.ShowModal;
end;
procedure TGLMFrm.PartIEntry;
var
i, j, k, vect : integer;
min, max, group, ngrps : integer;
CodePattern : IntDyneMat;
cellstring: string;
begin
if NReptDep > 0 then // create observations for each replication of the N cases
begin
for i := 1 to NreptDep do
begin
ReptDepPos[i-1] := i; // datagrid pos. of a repeated measure
for j := 1 to NoCases do
begin
DataGrid[totalobs,gencount] := j; // case no. in col. 0
k := ReptDepID[i-1];
DataGrid[totalobs,gencount+1] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,j]));
totalobs := totalobs + 1;
end;
end; // next i repeated measure
gencount := gencount + 2;
end
else
begin // no repeated measures - just need case numbers in data grid pos 0
for i := 1 to NoCases do DataGrid[i-1,gencount] := i;
totalobs := NoCases;
gencount := gencount + 1;
end;
GenLabels[0] := 'Obs.';
if NReptDep > 0 then GenLabels[1] := 'Repeated';
// Enter the continuous dependent variables into the data grid
if NContDep > 0 then
begin
for j := 1 to NContDep do
begin
ContDepPos[j-1] := gencount;
for i := 1 to NoCases do
begin
k := ContDepID[j-1];
DataGrid[i-1,gencount] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i]));
end;
GenLabels[gencount] := ContDepCode.Items.Strings[j-1];
gencount := gencount + 1;
end;
end; // end if NContDep > 0
// Enter categorical dependent variables in the data grid
if NCatDep > 0 then
begin
// get no. of categories - 1 for no of vectors to generate for each
// categorical variable
for j := 1 to NCatDep do
begin
CatDepPos[j-1] := gencount;
k := CatDepID[j-1];
min := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,1])));
max := min;
for i := 1 to NoCases do
begin
group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i])));
if group > max then max := group;
if group < min then min := group;
end;
ngrps := max-min+1;
SetLength(CodePattern,ngrps+1,ngrps+1);
if TypeGroup.ItemIndex = 0 then // dummy coding
DummyCodes(min,max,CodePattern);
if TypeGroup.ItemIndex = 1 then // effect coding
EffectCodes(min,max,CodePattern);
if TypeGroup.ItemIndex = 2 then // orthogonal coding
OrthogCodes(min,max,CodePattern);
// Now, generate vectors for the categorical variable j
for vect := 1 to (max - min) do // vector no.
begin
for i := 1 to NoCases do
begin
group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i])));
DataGrid[i-1,gencount + vect - 1] := CodePattern[group,vect];
end;
cellstring := format('%s_%d',[CatDepCode.Items.Strings[j-1],vect]);
GenLabels[gencount + vect - 1] := cellstring;
end;
gencount := gencount + (max - min); // new no. of variables
end; // next categorical variable j
end; // if no. of dependent categorical variables greater than zero
codepattern := nil;
end;
procedure TGLMFrm.PartIIEntry;
var
i, j, k, vect, lastdep, row : integer;
min, max, group, ngrps : integer;
CodePattern : IntDyneMat;
cellstring : string;
value : double;
begin
lastdep := gencount; // datagrid position of last dependent variable
// This section develops vectors for the independent variables. If there
// are repeated measures, generate person vectors first.
if NReptDep > 0 then
begin
min := 1;
max := NoCases;
ngrps := max-min+1;
SetLength(CodePattern,ngrps+1,ngrps+1);
if TypeGroup.ItemIndex = 0 then // dummy coding
DummyCodes(min,max,CodePattern);
if TypeGroup.ItemIndex = 1 then // effect coding
EffectCodes(min,max,CodePattern);
if TypeGroup.ItemIndex = 2 then // orthogonal coding
OrthogCodes(min,max,CodePattern);
for vect := 1 to (max - min) do // vector no.
begin
for i := 1 to totalobs do // NoCases
begin
group := round(DataGrid[i-1,0]);
DataGrid[i-1,gencount + vect - 1] := CodePattern[group,vect];
end;
ReptIndepPos[vect-1] := gencount + vect - 1;
cellstring := Format('p%d', [vect]);
GenLabels[gencount + vect - 1] := cellstring;
end;
gencount := gencount + (max - min); // new no. of variables
end; // end generation of person codes
// generate vectors for the repeated treatments if replications used
if NReptDep > 0 then
begin
min := 1;
max := NReptDep;
ngrps := max-min+1;
SetLength(CodePattern,ngrps+1,ngrps+1);
if TypeGroup.ItemIndex = 0 then // dummy coding
DummyCodes(min,max,CodePattern);
if TypeGroup.ItemIndex = 1 then // effect coding
EffectCodes(min,max,CodePattern);
if TypeGroup.ItemIndex = 2 then // orthogonal coding
OrthogCodes(min,max,CodePattern);
for vect := 1 to (max - min) do // vector no.
begin
for i := 1 to totalobs do // NoCases
begin
group := ((i - 1) div NoCases) + 1;
DataGrid[i-1,gencount + vect - 1] := CodePattern[group,vect];
end;
ReptTrtPos[vect-1] := gencount + vect - 1;
cellstring := format('IR_%d',[vect]);
GenLabels[gencount + vect - 1] := cellstring;
end;
gencount := gencount + (max - min); // new no. of variables
end;
oldcount := gencount;
// Next, add vectors for independent fixed categorical variables
if NFixedIndep > 0 then
begin
// get no. of categories - 1 for no of vectors to generate for each
// categorical variable
for j := 1 to NFixedIndep do
begin
FixedIndepPos[j-1] := gencount; // first vector position in datagrid
k := FixedIndepID[j-1];
min := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,1])));
max := min;
for i := 1 to NoCases do
begin
group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i])));
if group > max then max := group;
if group < min then min := group;
end;
ngrps := max-min+1;
SetLength(CodePattern,ngrps+1,ngrps+1);
if TypeGroup.ItemIndex = 0 then // dummy coding
DummyCodes(min,max,CodePattern);
if TypeGroup.ItemIndex = 1 then // effect coding
EffectCodes(min,max,CodePattern);
if TypeGroup.ItemIndex = 2 then // orthogonal coding
OrthogCodes(min,max,CodePattern);
// Now, generate vectors for the categorical variable j
for vect := 1 to (max - min) do // vector no.
begin
for i := 1 to NoCases do
begin
group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i])));
DataGrid[i-1,gencount + vect - 1] := CodePattern[group,vect];
end;
cellstring := format('%s_%d',[FixedIndepCode.Items.Strings[j-1],vect]);
GenLabels[gencount + vect - 1] := cellstring;
end;
gencount := gencount + (max - min); // new no. of variables
end; // next categorical variable j
end; // end generation of fixed effect codes
// Next, add vectors for independent random categorical variables
oldcount := gencount;
if NRndIndep > 0 then
begin
// get no. of categories - 1 for no of vectors to generate for each
// categorical variable
for j := 1 to NRndIndep do
begin
RndIndepPos[j-1] := gencount; // pos. of first vector in datagrid
k := RndIndepID[j-1];
min := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,1])));
max := min;
for i := 1 to NoCases do
begin
group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i])));
if group > max then max := group;
if group < min then min := group;
end;
ngrps := max-min+1;
SetLength(CodePattern,ngrps+1,ngrps+1);
if TypeGroup.ItemIndex = 0 then // dummy coding
DummyCodes(min,max,CodePattern);
if TypeGroup.ItemIndex = 1 then // effect coding
EffectCodes(min,max,CodePattern);
if TypeGroup.ItemIndex = 2 then // orthogonal coding
OrthogCodes(min,max,CodePattern);
// Now, generate vectors for the categorical variable j
for vect := 1 to (max - min) do // vector no.
begin
for i := 1 to NoCases do
begin
group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i])));
DataGrid[i-1,gencount + vect - 1] := CodePattern[group,vect];
end;
cellstring := format('%s_%d',[RndIndepCode.Items.Strings[j-1],vect]);
GenLabels[gencount + vect - 1] := cellstring;
end;
gencount := gencount + (max - min); // new no. of variables
end; // next categorical variable j
end; // end generation of random effect codes
// Next, add covariates
if NCovIndep > 0 then
begin
for j := 1 to NCovIndep do
begin
CovIndepPos[j-1] := gencount;
for i := 1 to NoCases do
begin
k := CovIndepID[j-1];
DataGrid[i-1,gencount] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i]));
end;
GenLabels[gencount] := CovariateCode.Items.Strings[j-1];
gencount := gencount + 1;
end;
end; // end generation of covariate codes
// if repeated measures used, copy generated vectors for each replication
if NReptDep > 0 then
begin
for j := 1 to NReptDep - 1 do
begin
for i := 1 to NoCases do
begin
for k := lastdep + (NoCases-1) +(NReptDep-1) + 1 to gencount do
begin
value := DataGrid[i-1,k-1];
row := (j * NoCases) + i - 1;
DataGrid[row,k-1] := value;
end; // next k column in data grid
end; // next case
end; // next repeated measure
end; // if repeated measures used
// Now generate product vectors for the interactions
if NoInterDefs > 0 then
begin
for j := 0 to NoInterDefs - 1 do
begin
// parse an interaction line into components (abbreviations) and
// get product of vectors corresponding to each
InteractPos[j] := gencount;
cellstring := InteractList.Items.Strings[j];
GenInterVecs(cellstring);
gencount := gencount + NInteractVecs[j];
end;
end; // end generation of interaction codes
codepattern := nil;
end;
procedure TGLMFrm.ModelIAnalysis(AReport: TStrings);
var
block, i, j, k, NEntered, index, noblocks, priorentered : integer;
cellstring : string;
labelstr : string;
R, R2Increment, SSx, sum, constant, FullR2 : double;
df1, df2, F, FProbF, StdErrB, PredSS, PredMS : double;
SSt, VarEst, SSres, StdErrEst, AdjR2 : double;
begin
NEntered := 0;
priorentered := 0;
OldR2 := 0;
// enter the dependent variable first
if NContDep > 0 then
begin
ColSelected[0] := ContDepPos[0];
Labels[0] := GenLabels[1];
end
else begin
ColSelected[0] := ReptDepPos[0];
Labels[0] := GenLabels[1];
end;
NEntered := NEntered + 1;
// Enter independent variables as indicated in indorderbox then interactions
// until the total model is analyzed. Then delete each term to get a
// restricted model and compare to the full model.
noblocks := IndOrderBox.Items.Count;
SetLength(TypeISS,noblocks);
SetLength(TypeIISS,noblocks);
SetLength(TypeIMS,noblocks);
SetLength(TypeIIMS,noblocks);
SetLength(TypeIDF1,noblocks);
SetLength(TypeIDF2,noblocks);
SetLength(TypeIIDF1,noblocks);
SetLength(TypeIIDF2,noblocks);
SetLength(TypeIF,noblocks);
SetLength(TypeIProb,noblocks);
SetLength(TypeIIF,noblocks);
SetLength(TypeIIProb,noblocks);
for block := 0 to noblocks - 1 do
begin
// get index of the abbreviation of term to enter and find corresponding
// vector(s) to place in the equation
cellstring := IndOrderBox.Items.Strings[block];
// check for covariates first
if NCovIndep > 0 then
begin
for i := 0 to NCovIndep-1 do
begin
if cellstring = CovariateCode.Items.Strings[i] then // matched!
begin
index := i; // index of covariate code
ColSelected[NEntered] := CovIndepPos[index];
labelstr := Format('%s', [CovariateCode.Items[index]]);
Labels[NEntered] := labelstr;
NEntered := NEntered + 1;
break;
end;
end;
end;
// check for fixed effect variables next
if NFixedIndep > 0 then
begin
for i := 0 to NFixedIndep-1 do
begin
if cellstring = FixedIndepCode.Items.Strings[i] then
begin
index := i;
for j := 0 to NFixVecIndep[index]-1 do
begin
ColSelected[NEntered] := FixedIndepPos[index] + j;
labelstr := Format('%s_%d',[FixedIndepCode.Items[index],j+1]);
Labels[NEntered] := labelstr;
NEntered := NEntered + 1;
end;
break;
end;
end;
end;
// Check for random effects variables next
if NRndIndep > 0 then
begin
for i := 0 to NRndIndep-1 do
begin
if cellstring = RndIndepCode.Items.Strings[i] then
begin
index := i;
for j := 0 to NRndVecIndep[index]-1 do
begin
ColSelected[NEntered] := RndIndepPos[index] + j;
labelstr := Format('%s_%d',[RndIndepCode.Items[index],j+1]);
Labels[NEntered] := labelstr;
NEntered := NEntered + 1;
end;
break;
end;
end;
end;
// check for interactions next
if NoInterDefs > 0 then
begin
for i := 0 to NoInterDefs-1 do
begin
if cellstring = InteractList.Items.Strings[i] then
begin
for j := 0 to NInteractVecs[i]-1 do
begin
ColSelected[NEntered] := InteractPos[i] + j;
labelstr := Format('%s%d_%d',['IA',i+1,j+1]);
Labels[NEntered] := labelstr;
NEntered := NEntered + 1;
end;
break;
end;
end;
end; // check for interaction variables
// check for repeated measures variables (person codes)
if NReptDep > 0 then
begin // look for 'IP' in cellstring
labelstr := copy(cellstring,0,2);
if labelstr = 'IP' then // person vectors were generated
begin
for i := 0 to NoCases - 2 do
begin
ColSelected[NEntered] := ReptIndepPos[i];
Labels[NEntered] := GenLabels[ReptIndepPos[i]];
NEntered := NEntered + 1;
end;
end;
end;
// check for repeated treatments
if NReptDep > 0 then
begin // look for 'IR' in cellstring
labelstr := copy(cellstring,0,2);
if labelstr = 'IR' then // repeated treatment vectors were generated
begin
for i := 0 to NReptDep - 2 do
begin
ColSelected[NEntered] := ReptTrtPos[i];
Labels[NEntered] := GenLabels[ReptTrtPos[i]];
NEntered := NEntered + 1;
end;
end;
end;
RegAnal(NEntered, AReport);
R := sqrt(R2);
df1 := Nentered - 1; // no. of independent variables
df2 := totalobs - df1 - 1; // N - no. independent - 1
SSt := (totalobs-1) * Vars[0];
SSres := SSt * (1.0 - R2);
VarEst := SSres / df2;
if (VarEst > 0.0) then
StdErrEst := sqrt(VarEst)
else
begin
ErrorMsg('Error in computing variance estimate.');
StdErrEst := 0.0;
end;
if (R2 < 1.0) and (df2 > 0.0) then
F := (R2 / df1) / ((1.0-R2)/ df2)
else
F := 0.0;
FProbF := probf(F,df1,df2);
AdjR2 := 1.0 - (1.0 - R2) * (totalobs - 1) / df2;
AReport.Add(' R R2 F Prob. > F DF1 DF2 ');
AReport.Add('-------- ---------- ---------- ---------- ----- -----');
AReport.Add('%8.3f %10.3f %10.3f %10.3f %5.0f %5.0f', [R, R2, F, FProbF, df1, df2]);
AReport.Add('');
AReport.Add('Adjusted R Squared: %10.3f', [AdjR2]);
AReport.Add('Std. Error of Estimate: %10.3f', [StdErrEst]);
AReport.Add('');
AReport.Add('Variable Beta B Std.Error t Prob. > t ');
AReport.Add('---------- ---------- ---------- ---------- ---------- ----------');
df1 := 1.0;
sum := 0.0;
for i := 0 to Nentered - 2 do
begin
SSx := (totalobs-1) * Vars[i+1];
sum := sum + B[i] * means[i+1];
if invmatrix[i,i] > 1.0e-15 then
begin
StdErrB := VarEst / (SSx * (1.0 / invmatrix[i,i]));
StdErrB := sqrt(StdErrB);
if StdErrB > 0.0 then F := B[i] / StdErrB else F := 0.0;
FProbF := probf(F*F,df1,df2);
end else
begin
StdErrB := 0.0;
F := 0.0;
FProbF := 0.0;
end;
AReport.Add('%10s %10.3f %10.3f %10.3f %10.3f %10.3f', [Labels[i+1], Beta[i] ,B[i], StdErrB, F, FProbF]);
end;
AReport.Add('');
constant := means[0] - sum;
AReport.Add('Constant: %10.3f', [constant]);
// test increment in R2 for this block
R2Increment := R2 - OldR2;
if priorentered > 0 then
df1 := (NEntered-1) - (priorentered-1)
else
df1 := NEntered - 1;
df2 := totalobs - NEntered;
TypeIDF1[block] := df1;
TypeIDF2[block] := df2;
TypeISS[block] := (R2 - OldR2) * SSt;
TypeIMS[block] := TypeISS[block] / df1;
F := ((R2 - OldR2)/ df1) / ((1.0 - R2) / df2);
TypeIF[block] := F;
FProbF := probf(F,df1,df2);
TypeIProb[block] := FProbF;
AReport.Add('Increment in Squared R: %10.3f', [R2Increment]);
AReport.Add('F: %10.3f', [F]);
AReport.Add(' with d.o.f. %10.0f and %.0f',[df1, df2]); // df is double! - why?
AReport.Add(' and Prob > F %10.3f', [FProbF]);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
OldR2 := R2;
priorentered := NEntered;
// setup for next block analysis
WorkMat := nil;
StdDevs := nil;
Vars := nil;
means := nil;
Beta := nil;
B := nil;
invmatrix := nil;
rxy := nil;
indmatrix := nil;
rmatrix := nil;
end; // next variable block
// Next, obtain the unique (Type II values) by elimination of each block
// from the full model and testing the decrement in R2
FullR2 := R2; // save previously obtained full model R2
for i := 0 to NoBlocks - 1 do
begin
NEntered := 0;
// enter the dependent variable first
if NContDep > 0 then
begin
ColSelected[0] := ContDepPos[0];
Labels[0] := GenLabels[1];
end
else begin
ColSelected[0] := ReptDepPos[0];
Labels[0] := GenLabels[1];
end;
NEntered := NEntered + 1;
for block := 0 to NoBlocks - 1 do
begin
if i = block then
continue // delete this block
else
begin // enter the remaining blocks
cellstring := IndOrderBox.Items.Strings[block];
// if a covariate, include it
if NCovIndep > 0 then
begin
for j := 0 to NCovIndep-1 do
begin
if cellstring = CovariateCode.Items.Strings[j] then // matched!
begin
index := j; // index of covariate code
ColSelected[NEntered] := CovIndepPos[index];
Labels[NEntered] := Format('%s', [CovariateCode.Items[index]]);
NEntered := NEntered + 1;
break;
end;
end;
end;
// check for fixed effect variables next
if NFixedIndep > 0 then
begin
for j := 0 to NFixedIndep-1 do
begin
if cellstring = FixedIndepCode.Items.Strings[j] then
begin
index := j;
for k := 0 to NFixVecIndep[index]-1 do
begin
ColSelected[NEntered] := FixedIndepPos[index] + k;
Labels[NEntered] := Format('%s_%d', [FixedIndepCode.Items[index], k+1]);
NEntered := NEntered + 1;
end;
break;
end;
end;
end;
// Check for random effects variables next
if NRndIndep > 0 then
begin
for j := 0 to NRndIndep-1 do
begin
if cellstring = RndIndepCode.Items.Strings[j] then
begin
index := j;
for k := 0 to NRndVecIndep[index]-1 do
begin
ColSelected[NEntered] := RndIndepPos[index] + k;
Labels[NEntered] := Format('%s_%d', [RndIndepCode.Items[index], k+1]);
NEntered := NEntered + 1;
end;
end;
break;
end;
end;
// check for interactions next
if NoInterDefs > 0 then
begin
for j := 0 to NoInterDefs-1 do
begin
if cellstring = InteractList.Items.Strings[j] then
begin
for k := 0 to NInteractVecs[j]-1 do
begin
ColSelected[NEntered] := InteractPos[j] + k;
Labels[NEntered] := Format('%s%d_%d', ['IA', j+1, k+1]);
NEntered := NEntered + 1;
end;
break;
end; // end if
end; // next j
end; // end if interdefs > 0
end; // entry of remaining blocks
end; // enter next block not equal to block i
RegAnal(NEntered, AReport); // compute restricted model
if R2 > 0.0 then R := sqrt(R2) else R := 0.0;
df1 := Nentered; // no. of independent variables
df2 := totalobs - df1 - 1; // N - no. independent - 1
SSt := (totalobs-1) * Vars[0];
SSres := SSt * (1.0 - R2);
VarEst := SSres / df2;
if (VarEst > 0.0) then
StdErrEst := sqrt(VarEst)
else
begin
ErrorMsg('Error in computing variance estimate.');
StdErrEst := 0.0;
end;
if (R2 < 1.0) and (df2 > 0.0) then F := (R2 / df1) / ((1.0-R2)/ df2)
else F := 0.0;
FProbF := probf(F,df1,df2);
AdjR2 := 1.0 - (1.0 - R2) * (totalobs - 1) / df2;
AReport.Add(' R R2 F Prob. > F DF1 DF2 ');
AReport.Add('-------- ---------- ---------- ---------- ----- -----');
AReport.Add('%8.3f %10.3f %10.3f %10.3f %5.0f %5.0f', [R, R2, F, FProbF, df1, df2]);
AReport.Add('');
AReport.Add('Adjusted R Squared: %10.3f', [AdjR2]);
AReport.Add('Std. Error of Estimate: %10.3f', [StdErrEst]);
AReport.Add('');
AReport.Add('Variable Beta B Std.Error t Prob. > t ');
AReport.Add('---------- ---------- ---------- ---------- ---------- ----------');
df1 := 1.0;
sum := 0.0;
for j := 0 to Nentered - 2 do
begin
SSx := (totalobs-1) * Vars[j+1];
sum := sum + B[j] * means[j+1];
if invmatrix[j,j] > 1.0e-18 then
StdErrB := VarEst / (SSx * (1.0 / invmatrix[j,j]))
else StdErrB := 0.0;
if StdErrB > 0.0 then StdErrB := sqrt(StdErrB);
if StdErrB > 0.0 then F := B[j] / StdErrB else F := 0.0;
FProbF := probf(F*F,df1,df2);
AReport.Add('%10s %10.3f %10.3f %10.3f %10.3f %10.3f', [Labels[j+1], Beta[j] ,B[j], StdErrB, F, FProbF]);
end;
AReport.Add('');
constant := means[0] - sum;
AReport.Add('Constant: %10.3f', [constant]);
// Now compute unique contribution of block left out (Type II)
R2Increment := FullR2 - R2;
df1 := (novars - 2) - (NEntered - 1); // k1 - k2
df2 := totalobs - (novars - 2) - 1;
TypeIIDF1[i] := df1;
TypeIIDF2[i] := df2;
TypeIISS[i] := (FullR2 - R2) * SSt;
TypeIIMS[i] := TypeIISS[i] / df1;
F := ((FullR2 - R2)/ df1) / ((1.0 - FullR2) / df2);
TypeIIF[i] := F;
FProbF := probf(F,df1,df2);
TypeIIProb[i] := FProbF;
AReport.Add('Decrement in Squared R: %10.3f', [R2Increment]);
AReport.Add('F: %10.3f', [F]);
AReport.Add(' with d.o.f. %10.0f and %.0f',[df1, df2]);
AReport.Add(' and Prob > F %10.3f', [FProbF]);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
// setup for next block analysis
WorkMat := nil;
StdDevs := nil;
Vars := nil;
means := nil;
Beta := nil;
B := nil;
invmatrix := nil;
rxy := nil;
indmatrix := nil;
rmatrix := nil;
end; // next i block selected for elimination
// Show summary table of Type I and Type II tests
AReport.Add('SUMMARY TABLE FOR GLM EFFECTS');
AReport.Add('');
AReport.Add('Incremental Effects:');
AReport.Add('SOURCE DF1 DF2 SS MS F Prob > F');
AReport.Add('---------- ---- ---- ---------- ---------- ---------- --------');
for i := 0 to NoBlocks - 1 do
begin
cellstring := IndOrderBox.Items.Strings[i];
AReport.Add('%10s %4.0f %4.0f %10.3f %10.3f %10.3f %8.3f',
[cellstring,TypeIDF1[i],TypeIDF2[i],TypeISS[i],TypeIMS[i],TypeIF[i],TypeIProb[i]]
);
end;
AReport.Add('');
AReport.Add('Unique Effects:');
AReport.Add('SOURCE DF1 DF2 SS MS F Prob > F');
AReport.Add('---------- ---- ---- ---------- ---------- ---------- --------');
for i := 0 to NoBlocks - 1 do
begin
cellstring := IndOrderBox.Items.Strings[i];
AReport.Add('%10s %4.0f %4.0f %10.3f %10.3f %10.3f %8.3f',
[cellstring,TypeIIDF1[i],TypeIIDF2[i],TypeIISS[i],TypeIIMS[i],TypeIIF[i],TypeIIProb[i]]
);
end;
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
// Show Anova Results for fixed and/or covariates
if (NRndIndep = 0) and (NReptDep = 0) then // must be fixed and/or covariate only design
begin
if (NFixedIndep > 0) or (NCovIndep > 0) then // fixed effects
begin
df1 := novars - 2; // k1 (note: novars contains ID variable, dep, independents)
PredSS := SSt * FullR2;
PredMS := PredSS / df1;
df2 := totalobs - df1 - 1; // residual df
SSres := SSt * (1.0 - FullR2);
VarEst := SSres / df2; // ms residual
F := PredMS / VarEst;
FProbF := probf(F,df1,df2);
AReport.Add('SOURCE DF SS MS F Prob > F');
AReport.Add('-------------------- ---- ---------- ---------- ---------- --------');
AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %8.3f', ['Full Model', df1, PredSS, PredMS, F, FProbF]);
for i := 0 to NoBlocks - 1 do
begin
F := TypeIMS[i] / VarEst;
FProbF := probf(F,TypeIDF1[i],df2);
cellstring := IndOrderBox.Items.Strings[i];
AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %8.3f', [cellstring, TypeIDF1[i], TypeISS[i], TypeIMS[i], F, FProbF]);
end;
AReport.Add('%20s %4.0f %10.3f %10.3f', ['Residual', df2, SSres, VarEst]);
AReport.Add('%20s %4d %10.3f', ['Total', totalobs-1, SSt]);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
end;
end;
// Show Anova Results for random effects and/or covariates
if (NFixedIndep = 0) and (NReptDep = 0) then // must be random only or covariate only design
begin
if (NRndIndep > 0) or (NCovIndep > 0) then // random and/or covariate effects
begin
df1 := novars - 2; // k1 (note: novars contains ID variable, dep, independents)
PredSS := SSt * FullR2;
PredMS := PredSS / df1;
df2 := totalobs - df1 - 1; // residual df
SSres := SSt * (1.0 - FullR2);
VarEst := SSres / df2; // ms residual
F := PredMS / VarEst;
FProbF := probf(F,df1,df2);
AReport.Add('SOURCE DF SS MS F Prob > F');
AReport.Add('-------------------- ---- ---------- ---------- ---------- --------');
AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %8.3f', ['Full Model', df1, PredSS, PredMS, F, FProbF]);
for i := 0 to NoBlocks - 1 do
begin
F := TypeIMS[i] / VarEst;
FProbF := probf(F,TypeIDF1[i],df2);
AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %8.3f', [Labels[i+1], TypeIDF1[i], TypeISS[i], TypeIMS[i], F, FProbF]);
end;
AReport.Add('%20s %4.0f %10.3f %10.3f', ['Residual', df2, SSres, VarEst]);
AReport.Add('%20s %4d %10.3f', ['Total', totalobs-1, SSt]);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
end;
end;
// show effects for repeated measures ANOVA (and covariates)
if NReptDep > 0 then
begin
df1 := novars - 2; // k1 (note: novars contains ID variable, dep, independents)
PredSS := SSt * FullR2;
PredMS := PredSS / df1;
df2 := totalobs - df1 - 1; // residual df
SSres := SSt * (1.0 - FullR2);
VarEst := SSres / df2; // ms residual
F := PredMS / VarEst;
FProbF := probf(F,df1,df2);
AReport.Add('SOURCE DF SS MS F Prob > F');
AReport.Add('-------------------- ---- ---------- ---------- ---------- --------');
AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %8.3f', ['Full Model', df1, PredSS, PredMS, F, FProbF]);
for i := 0 to NoBlocks - 1 do
begin
F := TypeIMS[i] / VarEst;
FProbF := probf(F,TypeIDF1[i],df2);
AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %8.3f', [Labels[i+1], TypeIDF1[i], TypeISS[i], TypeIMS[i], F, FProbF]);
end;
AReport.Add('%20s %4.0f %10.3f %10.3f', ['Residual', df2, SSres, VarEst]);
AReport.Add('%20s %4d %10.3f', ['Total', totalobs-1, SSt]);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
end;
// clean up the heap
TypeIIProb := nil;
TypeIIF := nil;
TypeIProb := nil;
TypeIF := nil;
TypeIIDF2 := nil;
TypeIIDF1 := nil;
TypeIDF2 := nil;
TypeIDF1 := nil;
TypeIIMS := nil;
TypeIMS := nil;
TypeIISS := nil;
TypeISS := nil;
end;
procedure TGLMFrm.ModelIIAnalysis(AReport: TStrings);
var
block, i, j, NEntered, index, noblocks : integer;
NLeft, NRight : integer;
cellstring : string;
labelstr : string;
begin
NEntered := 0;
OldR2 := 0;
// enter the dependent variables first
if NContDep > 0 then
begin
for i := 0 to NContDep - 1 do
begin
ColSelected[i] := ContDepPos[i];
Labels[i] := GenLabels[i+1];
NEntered := NEntered + 1;
end;
end;
if NReptDep > 0 then
begin
for i := 0 to NReptDep - 1 do
begin
ColSelected[NEntered+i] := ReptDepPos[i];
Labels[NEntered+i] := GenLabels[NEntered+i+1];
NEntered := NEntered + 1;
end;
end;
if NCatDep > 0 then
begin
for i := 0 to NCatDep - 1 do
begin
for j := 0 to NFixVecDep[i]-1 do
begin
ColSelected[NEntered+j] := CatDepPos[j];
Labels[NEntered+j] := GenLabels[NEntered+j+1];
NEntered := NEntered + 1;
end;
end;
end;
// Enter the no. of dependent variables in the left list box of canonical
NLeft := NEntered;
// Enter independent variables as indicated in indorderbox then interactions
// until the total model is analyzed. Then delete each term to get a
// restricted model and compare to the full model.
noblocks := IndOrderBox.Items.Count;
SetLength(TypeISS,noblocks);
SetLength(TypeIISS,noblocks);
SetLength(TypeIMS,noblocks);
SetLength(TypeIIMS,noblocks);
SetLength(TypeIDF1,noblocks);
SetLength(TypeIDF2,noblocks);
SetLength(TypeIIDF1,noblocks);
SetLength(TypeIIDF2,noblocks);
SetLength(TypeIF,noblocks);
SetLength(TypeIProb,noblocks);
SetLength(TypeIIF,noblocks);
SetLength(TypeIIProb,noblocks);
for block := 0 to noblocks - 1 do
begin
// get index of the abbreviation of term to enter and find corresponding
// vector(s) to place in the equation
cellstring := IndOrderBox.Items.Strings[block];
// check for covariates first
if NCovIndep > 0 then
begin
for i := 0 to NCovIndep-1 do
begin
if cellstring = CovariateCode.Items.Strings[i] then // matched!
begin
index := i; // index of covariate code
ColSelected[NEntered] := CovIndepPos[index];
labelstr := format('%s',[CovariateCode.Items.Strings[index]]);
Labels[NEntered] := labelstr;
NEntered := NEntered + 1;
break;
end;
end;
end;
// check for fixed effect variables next
if NFixedIndep > 0 then
begin
for i := 0 to NFixedIndep-1 do
begin
if cellstring = FixedIndepCode.Items.Strings[i] then
begin
index := i;
for j := 0 to NFixVecIndep[index]-1 do
begin
ColSelected[NEntered] := FixedIndepPos[index] + j;
labelstr := format('%s_%d',[FixedIndepCode.Items.Strings[index],j+1]);
Labels[NEntered] := labelstr;
NEntered := NEntered + 1;
end;
break;
end;
end;
end;
// Check for random effects variables next
if NRndIndep > 0 then
begin
for i := 0 to NRndIndep-1 do
begin
if cellstring = RndIndepCode.Items.Strings[i] then
begin
index := i;
for j := 0 to NRndVecIndep[index]-1 do
begin
ColSelected[NEntered] := RndIndepPos[index] + j;
labelstr := format('%s_%d',[RndIndepCode.Items.Strings[index],j+1]);
Labels[NEntered] := labelstr;
NEntered := NEntered + 1;
end;
end;
break;
end;
end;
// check for interactions next
if NoInterDefs > 0 then
begin
for i := 0 to NoInterDefs-1 do
begin
if cellstring = InteractList.Items.Strings[i] then
begin
for j := 0 to NInteractVecs[i]-1 do
begin
ColSelected[NEntered] := InteractPos[i] + j;
labelstr := format('%s%d_%d',['IA',i+1,j+1]);
Labels[NEntered] := labelstr;
NEntered := NEntered + 1;
end;
end;
break;
end;
end; // check for interaction variables
// check for repeated measures variables (person codes)
if NReptDep > 0 then
begin // look for 'IP' in cellstring
labelstr := copy(cellstring,0,2);
if labelstr = 'IP' then // person vectors were generated
begin
for i := 0 to NoCases - 2 do
begin
ColSelected[NEntered] := ReptIndepPos[i];
Labels[NEntered] := GenLabels[ReptIndepPos[i]];
NEntered := NEntered + 1;
end;
end;
end;
// Enter the independent variables in the right list of canonical.
NRight := NEntered - NLeft;
// call cancor routine for this block
CanCor(NLeft, NRight, ColSelected, AReport);
end; // next block
TypeIIProb := nil;
TypeIIF := nil;
TypeIProb := nil;
TypeIIDF2 := nil;
TypeIIDF1 := nil;
TypeIDF2 := nil;
TypeIDF1 := nil;
TypeIIMS := nil;
TYPEIMS := nil;
TypeIISS := nil;
TypeISS := nil;
end;
procedure TGLMFrm.ModelIIIAnalysis(AReport: TStrings);
var
block, i, j, NEntered, index, noblocks: integer;
cellstring : string;
labelstr : string;
effstr : string;
R, SSx, sum, constant: double;
df1, df2, F, FProbF, StdErrB: double;
SSt, VarEst, SSres, StdErrEst, AdjR2 : double;
dfbetween, dferrbetween, dfwithin, dferrwithin : double;
ssbetween, sserrbetween, mserrbetween, sswithin, sserrwithin, mserrwithin : double;
betweenblock : integer;
totalss, totaldf : double;
begin
OldR2 := 0;
ColSelected[0] := ReptDepPos[0];
Labels[0] := GenLabels[1];
// Complete an individual regression analysis for each between subjects var.
// Enter each block containing between subjects variance including:
// (1) covariates
// (2) person vectors
// (3) fixed or random factors
// (4) the interactions among only fixed or random effects
noblocks := IndOrderBox.Items.Count;
SetLength(TypeISS,noblocks); // use for between subject effects
SetLength(TypeIISS,noblocks);// use for within subject effects
SetLength(TypeIMS,noblocks);
SetLength(TypeIIMS,noblocks);
SetLength(TypeIDF1,noblocks);
SetLength(TypeIDF2,noblocks);
SetLength(TypeIIDF1,noblocks);
SetLength(TypeIIDF2,noblocks);
SetLength(TypeIF,noblocks);
SetLength(TypeIProb,noblocks);
SetLength(TypeIIF,noblocks);
SetLength(TypeIIProb,noblocks);
for i := 0 to noblocks - 1 do
begin
TypeISS[i] := -1.0; // store indicator for block (-1 indicates no use)
TypeIISS[i] := -1.0;
end;
for block := 0 to noblocks - 1 do
begin
ColSelected[0] := ReptDepPos[0];
Labels[0] := GenLabels[1];
NEntered := 1;
cellstring := IndOrderBox.Items.Strings[block];
effstr := cellstring;
j := Pos('IR',cellstring);
if j <> 0 then continue;
// check for repeated measures variables (person codes)
if NReptDep > 0 then
begin // look for 'IP' in cellstring
labelstr := copy(cellstring,0,2);
if labelstr = 'IP' then // person vectors were generated
begin
betweenblock := block; // save block no. of between subject vectors
for i := 0 to NoCases - 2 do
begin
ColSelected[NEntered] := ReptIndepPos[i];
Labels[NEntered] := GenLabels[ReptIndepPos[i]];
NEntered := NEntered + 1;
end;
end;
end;
// check for fixed effect variables next
if NFixedIndep > 0 then
begin
for i := 0 to NFixedIndep-1 do
begin
if cellstring = FixedIndepCode.Items.Strings[i] then
begin
index := i;
for j := 0 to NFixVecIndep[index]-1 do
begin
ColSelected[NEntered] := FixedIndepPos[index] + j;
labelstr := Format('%s_%d', [FixedIndepCode.Items[index], j+1]);
Labels[NEntered] := labelstr;
NEntered := NEntered + 1;
end;
break;
end;
end;
end;
// Check for random effects variables next
if NRndIndep > 0 then
begin
for i := 0 to NRndIndep-1 do
begin
if cellstring = RndIndepCode.Items.Strings[i] then
begin
index := i;
for j := 0 to NRndVecIndep[index]-1 do
begin
ColSelected[NEntered] := RndIndepPos[index] + j;
labelstr := Format('%s_%d', [RndIndepCode.Items[index], j+1]);
Labels[NEntered] := labelstr;
NEntered := NEntered + 1;
end;
break;
end;
end;
end;
// check for interactions next
if NoInterDefs > 0 then
begin
for i := 0 to NoInterDefs-1 do
begin
if cellstring = InteractList.Items.Strings[i] then
begin
// eliminate any interactions containing 'IR'
j := Pos('IR',cellstring);
if j <> 0 then continue;
for j := 0 to NInteractVecs[i]-1 do
begin
ColSelected[NEntered] := InteractPos[i] + j;
labelstr := Format('%s%d_%d', ['IA',i+1,j+1]);
Labels[NEntered] := labelstr;
NEntered := NEntered + 1;
end;
break;
end;
end;
end; // check for interaction variables
// check for covariates
if NCovIndep > 0 then
begin
for i := 0 to NCovIndep-1 do
begin
if cellstring = CovariateCode.Items.Strings[i] then // matched!
begin
index := i; // index of covariate code
ColSelected[NEntered] := CovIndepPos[index];
labelstr := Format('%s', [CovariateCode.Items[index]]);
Labels[NEntered] := labelstr;
NEntered := NEntered + 1;
break;
end;
end;
end;
// do reg analysis and save sum of squares
RegAnal(NEntered, AReport);
R := sqrt(R2);
df1 := Nentered - 1; // no. of independent variables
TypeIDF1[block] := df1;
df2 := totalobs - df1 - 1; // N - no. independent - 1
SSt := (totalobs-1) * Vars[0];
SSres := SSt * (1.0 - R2);
VarEst := SSres / df2;
if (VarEst > 0.0) then
StdErrEst := sqrt(VarEst)
else
begin
ErrorMsg('Error in computing variance estimate.');
StdErrEst := 0.0;
end;
if (R2 < 1.0) and (df2 > 0.0) then
F := (R2 / df1) / ((1.0-R2)/ df2)
else
F := 0.0;
FProbF := probf(F,df1,df2);
AdjR2 := 1.0 - (1.0 - R2) * (totalobs - 1) / df2;
AReport.Add(' R R2 F Prob. > F DF1 DF2 ');
AReport.Add('-------- ---------- ---------- ---------- ----- -----');
AReport.Add('%8.3f %10.3f %10.3f %10.3f %5.0f %5.0f', [R, R2, F, FProbF, df1, df2]);
AReport.Add('Adjusted R Squared: %10.3f', [AdjR2]);
AReport.Add('');
AReport.Add('Std. Error of Estimate: %10.3f', [StdErrEst]);
AReport.Add('');
AReport.Add('Variable Beta B Std.Error t Prob. > t ');
AReport.Add('---------- ---------- ---------- ---------- ---------- ----------');
df1 := 1.0;
sum := 0.0;
for i := 0 to Nentered - 2 do
begin
SSx := (totalobs-1) * Vars[i+1];
sum := sum + B[i] * means[i+1];
if invmatrix[i,i] > 1.0e-15 then
begin
StdErrB := VarEst / (SSx * (1.0 / invmatrix[i,i]));
StdErrB := sqrt(StdErrB);
if StdErrB > 0.0 then F := B[i] / StdErrB else F := 0.0;
FProbF := probf(F*F,df1,df2);
end
else begin
StdErrB := 0.0;
F := 0.0;
FProbF := 0.0;
end;
cellstring := Format('%10s', [Labels[i+1]]);
AReport.Add('%10s %10.3f %10.3f %10.3f %10.3f %10.3f', [cellstring, Beta[i] ,B[i], StdErrB, F, FProbF]);
end;
constant := means[0] - sum;
AReport.Add('Constant: %10.3f', [constant]);
TypeISS[block] := R2 * SST;
AReport.Add('BETWEEN SUBJECT EFFECT:');
AReport.Add('SS for %-10s: %10.3f',[effstr,TypeISS[block]]);
AReport.Add('SS TOTAL: %10.3f',[SST]);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
end;
// Summarize between subject effects
totalss := 0.0;
totaldf := 0.0;
for i := 0 to noblocks - 1 do
begin
if TypeISS[i] < 0.0 then continue;
if betweenblock = i then
begin
ssbetween := TypeISS[i];
dfbetween := TypeIDF1[i];
end
else
begin
totalss := totalss + TypeISS[i];
totaldf := totaldf + TypeIDF1[i];
end;
end;
sserrbetween := ssbetween - totalss;
dferrbetween := dfbetween - totaldf;
mserrbetween := sserrbetween / dferrbetween;
AReport.Add('SUMMARY OF BETWEEN SUBJECT EFFECTS');
AReport.Add('SOURCE DF SS MS F Prob > F');
AReport.Add('-------------------- ---- ---------- ---------- ---------- --------');
AReport.Add('%-20s %4.0f %10.3f', ['Between Subjects', dfbetween, ssbetween]);
for i := 0 to noblocks - 1 do
begin
if TypeISS[i] < 0.0 then continue;
if betweenblock = i then continue; // already done above
TypeIMS[i] := TypeISS[i] / TypeIDF1[i];
TypeIF[i] := TypeIMS[i] / mserrbetween;
TypeIDF2[i] := dferrbetween;
TypeIProb[i] := probf(TypeIF[i],TypeIDF1[i],TypeIDF2[i]);
AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %10.3f',
[IndOrderBox.Items[i], TypeIDF1[i], TypeISS[i], TypeIMS[i], TypeIF[i], TypeIProb[i]]
);
end;
AReport.Add('%20s %4.0f %10.3f %10.3f', ['Error Between', dferrbetween, sserrbetween, mserrbetween]);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
// Now, get within subject effects
sswithin := SST - SSbetween;
dfwithin := totalobs - dfbetween - 1;
for block := 0 to noblocks - 1 do
begin
ColSelected[0] := ReptDepPos[0];
Labels[0] := GenLabels[1];
NEntered := 1;
cellstring := IndOrderBox.Items.Strings[block];
effstr := cellstring;
j := Pos('IR',cellstring);
if j = 0 then continue; // only select those for rep. treatments or interactions
// check for treatments
if NReptDep > 0 then
begin // look for 'IR' in cellstring
labelstr := copy(cellstring,0,2);
if labelstr = 'IR' then // repeated treatment vectors were generated
begin
for i := 0 to NReptDep - 2 do
begin
ColSelected[NEntered] := ReptTrtPos[i];
Labels[NEntered] := GenLabels[ReptTrtPos[i]];
NEntered := NEntered + 1;
end;
end;
end;
// check for interactions next
if NoInterDefs > 0 then
begin
for i := 0 to NoInterDefs-1 do
begin
if cellstring = InteractList.Items.Strings[i] then
begin
for j := 0 to NInteractVecs[i]-1 do
begin
ColSelected[NEntered] := InteractPos[i] + j;
labelstr := format('%s%d_%d',['IA',i+1,j+1]);
Labels[NEntered] := labelstr;
NEntered := NEntered + 1;
end;
break;
end;
end;
end; // check for interaction variables
// do reg analysis and save sum of squares
if NEntered < 2 then continue;
RegAnal(NEntered, AReport);
R := sqrt(R2);
df1 := Nentered - 1; // no. of independent variables
TypeIIDF1[block] := df1;
df2 := totalobs - df1 - 1; // N - no. independent - 1
SSt := (totalobs-1) * Vars[0];
SSres := SSt * (1.0 - R2);
VarEst := SSres / df2;
if (VarEst > 0.0) then
StdErrEst := sqrt(VarEst)
else
begin
MessageDlg('Error in computing variance estimate.', mtError,[mbOK], 0);
StdErrEst := 0.0;
end;
if (R2 < 1.0) and (df2 > 0.0) then
F := (R2 / df1) / ((1.0-R2)/ df2)
else
F := 0.0;
FProbF := probf(F,df1,df2);
AdjR2 := 1.0 - (1.0 - R2) * (totalobs - 1) / df2;
AReport.Add(' R R2 F Prob. > F DF1 DF2 ');
AReport.Add('-------- ---------- ---------- ---------- ----- -----');
AReport.Add('%8.3f %10.3f %10.3f %10.3f %5.0f %5.0f', [R, R2, F, FProbF, df1, df2]);
AReport.Add('');
AReport.Add('Adjusted R Squared: %10.3f', [AdjR2]);
AReport.Add('Std. Error of Estimate: %10.3f', [StdErrEst]);
AReport.Add('');
AReport.Add('Variable Beta B Std.Error t Prob. > t ');
AReport.Add('---------- ---------- ---------- ---------- ---------- ----------');
df1 := 1.0;
sum := 0.0;
for i := 0 to Nentered - 2 do
begin
SSx := (totalobs-1) * Vars[i+1];
sum := sum + B[i] * means[i+1];
if invmatrix[i,i] > 1.0e-15 then
begin
StdErrB := VarEst / (SSx * (1.0 / invmatrix[i,i]));
StdErrB := sqrt(StdErrB);
if StdErrB > 0.0 then F := B[i] / StdErrB else F := 0.0;
FProbF := probf(F*F,df1,df2);
end
else begin
StdErrB := 0.0;
F := 0.0;
FProbF := 0.0;
end;
cellstring := Format('%10s', [Labels[i+1]]);
AReport.Add('%10s %10.3f %10.3f %10.3f %10.3f %10.3f', [cellstring, Beta[i] ,B[i], StdErrB, F, FProbF]);
end;
constant := means[0] - sum;
AReport.Add('Constant: %10.3f', [constant]);
TypeIISS[block] := R2 * SST;
AReport.Add('BETWEEN SUBJECT EFFECT:');
AReport.Add('SS for %-10s: %10.3f',[effstr, TypeIISS[block]]);
AReport.Add('SS TOTAL: %10.3f',[SST]);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
end;
totalss := 0.0;
totaldf := 0.0;
for i := 0 to noblocks - 1 do // add sums of squares for within effects
begin
if TypeIISS[i] < 0.0 then continue;
totalss := totalss + TypeIISS[i];
totaldf := totaldf + TypeIIDF1[i];
end;
sserrwithin := sswithin - totalss;
dferrwithin := dfwithin - totaldf;
mserrwithin := sserrwithin / dferrwithin;
AReport.Add(' SUMMARY OF WITHIN SUBJECT EFFECTS');
AReport.Add('SOURCE DF SS MS F Prob > F');
AReport.Add('-------------------- ---- ---------- ---------- ---------- --------');
AReport.Add('%-20s %4.0f %10.3f', ['Within Subjects', dfwithin, sswithin]);
for i := 0 to noblocks - 1 do
begin
if TypeIISS[i] < 0.0 then continue;
TypeIIMS[i] := TypeIISS[i] / TypeIIDF1[i];
TypeIIF[i] := TypeIIMS[i] / mserrwithin;
TypeIIDF2[i] := dferrwithin;
TypeIIProb[i] := probf(TypeIIF[i],TypeIIDF1[i],TypeIIDF2[i]);
AReport.Add('%20s %4.0f %10.3f %10.3f %10.3f %10.3f',
[IndOrderBox.Items.Strings[i],TypeIIDF1[i],TypeIISS[i],TypeIIMS[i],TypeIIF[i],TypeIIProb[i]]
);
end;
AReport.Add('%20s %4.0f %10.3f %10.3f', ['Error Within', dferrwithin, sserrwithin, mserrwithin]);
AReport.Add('%20s %4d %10.3f', ['TOTAL', totalobs-1, SST]);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
// clean up the heap
TypeIIProb := nil;
TypeIIF := nil;
TypeIProb := nil;
TypeIF := nil;
TypeIIDF2 := nil;
TypeIIDF1 := nil;
TypeIDF2 := nil;
TypeIDF1 := nil;
TypeIIMS := nil;
TypeIMS := nil;
TypeIISS := nil;
TypeISS := nil;
end;
function TGLMFrm.CntIntActVecs(linestr: string): integer;
var
i, j, listcnt, varcount : integer;
cellstring : string;
asterisk : string;
blank : string;
abbrevList : array[1..5] of string;
vectcnt : array[1..5] of integer;
newline : string;
begin
asterisk := '*';
blank := ' ';
listcnt := 0;
cellstring := '';
newline := '';
for i := 1 to 5 do vectcnt[i] := 0;
// first, delete imbedded blanks that were there for readability
for i := 1 to length(linestr) do
begin
if linestr[i] <> blank then newline := newline + linestr[i];
end;
// Now, strip out substrings to each asterisk or end of string
while length(newline) > 0 do
begin
i := pos(asterisk,newline);
if i > 0 then // an asterisk found
begin
cellstring := copy(newline,0,i-1); // get abbreviation
delete(newline,1,i); // delete abbreviation and asterisk
listcnt := listcnt + 1;
AbbrevList[listcnt] := cellstring;
end
else begin // must be last abbreviation
cellstring := newline;
listcnt := listcnt + 1;
AbbrevList[listcnt] := cellstring;
newline := '';
end;
end;
// now get the associated number of columns for each abbreviation in the list
for i := 1 to listcnt do
begin
cellstring := AbbrevList[i];
// check for covariates
if NCovIndep > 0 then
begin
for j := 0 to NCovIndep - 1 do
begin
if cellstring = CovariateCode.Items.Strings[j] then
vectcnt[i] := 1;
end;
end;
// check for fixed effect vectors
if NFixedIndep > 0 then
begin
for j := 0 to NFixedIndep - 1 do
begin
if cellstring = FixedIndepCode.Items.Strings[j] then
vectcnt[i] := NFixVecIndep[j];
end;
end;
// check for random effect vectors
if NRndIndep > 0 then
begin
for j := 0 to NRndIndep - 1 do
begin
if cellstring = RndIndepCode.Items.Strings[j] then
vectcnt[i] := NRndVecIndep[j];
end;
end;
// check for repeated measures effect vectors
if NReptDep > 0 then
begin
if cellstring = RepTrtCode.Items.Strings[0] then
vectcnt[i] := NReptDep - 1;
end;
end; // next i in listcnt
// get total interaction vector count
varcount := 1;
for i := 1 to listcnt do varcount := varcount * vectcnt[i];
Result := varcount;
end;
procedure TGLMFrm.GenInterVecs(linestr: string);
var
i, j, k, l, m, n, col, listcnt, pos1, pos2, pos3, pos4, pos5: integer;
cellstring : string;
asterisk : string;
blank : string;
abbrevList : array[1..5] of string;
vectcnt : array[1..5] of integer;
fromcol : array[1..5] of integer;
newline : string;
begin
asterisk := '*';
blank := ' ';
listcnt := 0;
cellstring := '';
newline := '';
// first, delete imbedded blanks that were there for readability
for i := 1 to length(linestr) do
begin
if linestr[i] <> blank then newline := newline + linestr[i];
end;
// Now, strip out substrings to each asterisk or end of string
while length(newline) > 0 do
begin
i := pos(asterisk,newline);
if i > 0 then // an asterisk found
begin
cellstring := copy(newline,0,i-1); // get abbreviation
delete(newline,1,i); // delete abbreviation and asterisk
listcnt := listcnt + 1;
AbbrevList[listcnt] := cellstring;
end
else begin // must be last abbreviation
cellstring := newline;
listcnt := listcnt + 1;
AbbrevList[listcnt] := cellstring;
newline := '';
end;
end;
// now generate the associated number of columns for each abbreviation in the list
for i := 1 to listcnt do
begin
cellstring := AbbrevList[i];
// check for covariates
if NCovIndep > 0 then
begin
for j := 0 to NCovIndep - 1 do
begin
if cellstring = CovariateCode.Items.Strings[j] then
begin
vectcnt[i] := 1;
fromcol[i] := CovIndepPos[j];
break;
end;
end;
end;
// check for fixed effect vectors
if NFixedIndep > 0 then
begin
for j := 0 to NFixedIndep - 1 do
begin
if cellstring = FixedIndepCode.Items.Strings[j] then
begin
vectcnt[i] := NFixVecIndep[j];
fromcol[i] := FixedIndepPos[j];
break;
end;
end;
end;
// check for random effect vectors
if NRndIndep > 0 then
begin
for j := 0 to NRndIndep - 1 do
begin
if cellstring = RndIndepCode.Items.Strings[j] then
begin
vectcnt[i] := NRndVecIndep[j];
fromcol[i] := RndIndepPos[j];
break;
end;
end;
end;
// check for repeated measures
if NReptDep > 0 then
begin
if cellstring = RepTrtCode.Items.Strings[0] then
begin
vectcnt[i] := NReptDep - 1;
fromcol[i] := ReptTrtPos[0];
end;
end;
end; // next i in listcnt
// now generate the product vectors for 2-way interactions
col := gencount;
for i := 1 to vectcnt[1] do
begin
pos1 := fromcol[1] + i - 1;
for j := 1 to vectcnt[2] do
begin
pos2 := fromcol[2] + j - 1;
for m := 0 to totalobs - 1 do
datagrid[m,col] := datagrid[m,pos1] * datagrid[m,pos2];
cellstring := format('%s_%d*%s_%d',[AbbrevList[1],i,AbbrevList[2],j]);
GenLabels[col] := cellstring;
col := col + 1;
end;
end;
if listcnt = 3 then // Do 3-way interactions
begin
col := gencount;
for i := 1 to vectcnt[1] do
begin
pos1 := fromcol[1] + i - 1;
for j := 1 to vectcnt[2] do
begin
pos2 := fromcol[2] + j - 1;
for k := 1 to vectcnt[3] do
begin
pos3 := fromcol[3] + k - 1;
for m := 0 to totalobs - 1 do
datagrid[m,col] := datagrid[m,pos1] * datagrid[m,pos2] * datagrid[m,pos3];
cellstring := format('%s*%s*%s',[GenLabels[pos1],GenLabels[pos2],GenLabels[pos3]]);
GenLabels[col] := cellstring;
col := col + 1;
end; // next k
end; // next j
end; // next i
end; // if listcnt = 3
if listcnt = 4 then // Do 4-way interactions
begin
col := gencount;
for i := 1 to vectcnt[1] do
begin
pos1 := fromcol[1] + i - 1;
for j := 1 to vectcnt[2] do
begin
pos2 := fromcol[2] + j - 1;
for k := 1 to vectcnt[3] do
begin
pos3 := fromcol[3] + k - 1;
for l := 1 to vectcnt[4] do
begin
pos4 := fromcol[4] + l - 1;
for m := 0 to totalobs - 1 do
datagrid[m,col] := datagrid[m,pos1] *
datagrid[m,pos2] * datagrid[m,pos3] * datagrid[m,pos4];
cellstring := format('%s*%s*%s*%s',[GenLabels[pos1],
GenLabels[pos2],GenLabels[pos3],GenLabels[pos4]]);
GenLabels[col] := cellstring;
col := col + 1;
end; // next l
end; // next k
end; // next j
end; // next i
end; // if listcnt = 3
if listcnt = 5 then // Do 5-way interactions
begin
col := gencount;
for i := 1 to vectcnt[1] do
begin
pos1 := fromcol[1] + i - 1;
for j := 1 to vectcnt[2] do
begin
pos2 := fromcol[2] + j - 1;
for k := 1 to vectcnt[3] do
begin
pos3 := fromcol[3] + k - 1;
for l := 1 to vectcnt[4] do
begin
pos4 := fromcol[4] + l - 1;
for n := 1 to vectcnt[5] do
begin
pos5 := fromcol[5] + n - 1;
for m := 0 to totalobs - 1 do
datagrid[m,col] := datagrid[m,pos1] *
datagrid[m,pos2] * datagrid[m,pos3] *
datagrid[m,pos4] * datagrid[m,pos5];
cellstring := Format('%s*%s*%s*%s*%s',[GenLabels[pos1],
GenLabels[pos2],GenLabels[pos3],GenLabels[pos4],
GenLabels[pos5]]);
GenLabels[col] := cellstring;
col := col + 1;
end; // next n
end; // next l
end; // next k
end; // next j
end; // next i
end; // if listcnt = 3
end;
procedure TGLMFrm.CanCor(NLeft: integer; NRight: integer; GridPlace: IntDyneVec;
AReport: TStrings);
var
i, j, k, count, a_size, b_size, no_factors, IER: integer;
s, m, n, df1, df2, q, w, pcnt_extracted, trace : double;
minroot, critical_prob, Lambda, Pillia : double;
chisqr, HLTrace, chiprob, ftestprob, Roys, f, Hroot : double;
raa, rbb, rab, rba, bigmat, first_prod, second_prod : DblDyneMat;
char_equation, raainv, rbbinv, eigenvectors, norm_a, norm_b : DblDyneMat;
raw_a, raw_b, a_cors, b_cors, eigentrans, theta, tempmat : DblDyneMat;
mean, variance, stddev, roots, root_chi, chi_prob, pv_a, pv_b : DblDyneVec;
rd_a, rd_b, pcnt_trace : DblDyneVec;
root_df : IntDyneVec;
a_vars, b_vars : StrDyneVec;
selected : IntDyneVec;
RowLabels, ColLabels : StrDyneVec;
CanLabels : StrDyneVec;
title : string;
errorcode : boolean = false;
begin
count := 0;
k := 0;
no_factors := 0;
pcnt_extracted := 0.0;
trace := 0.0;
minroot := 0.0;
critical_prob := 0.0;
Pillia := 0.0;
chisqr := 0.0;
HLTrace := 0.0;
chiprob := 0.0;
// Get size of the Left and Right matrices (predictors and dependents)
a_size := NLeft;
b_size:= NRight;
novars:= a_size + b_size;
// allocate memory for matrices and vectors
SetLength(raa,NLeft+1,NLeft+1);
SetLength(rbb,NRight+1,NRight+1);
SetLength(rab,NLeft+1,NRight+1);
SetLength(rba,NRight+1,NLeft+1);
SetLength(bigmat,novars+1,novars+1);
SetLength(first_prod,novars+1,novars+1);
SetLength(second_prod,novars+1,novars+1);
SetLength(char_equation,novars+1,novars+1);
SetLength(raainv,NLeft,NLeft);
SetLength(rbbinv,NRight,NRight);
SetLength(eigenvectors,novars,novars);
SetLength(norm_a,novars,novars);
SetLength(norm_b,novars,novars);
SetLength(raw_a,novars,novars);
SetLength(raw_b,novars,novars);
SetLength(a_cors,NLeft+1,NLeft+1);
SetLength(b_cors,NRight+1,NRight+1);
SetLength(eigentrans,novars,novars);
SetLength(theta,novars,novars);
SetLength(tempmat,novars,novars);
SetLength(mean,novars);
SetLength(variance,novars);
SetLength(stddev,novars);
SetLength(roots,novars);
SetLength(root_chi,novars);
SetLength(chi_prob,novars);
SetLength(pv_a,novars);
SetLength(pv_b,novars);
SetLength(rd_a,novars);
SetLength(rd_b,novars);
SetLength(pcnt_trace,novars);
SetLength(root_df,novars);
SetLength(a_vars,NLeft);
SetLength(b_vars,NRight);
SetLength(CanLabels,novars);
SetLength(RowLabels,novars);
SetLength(ColLabels,novars);
SetLength(selected,novars);
//------------ WORK STARTS HERE! -------------------------------------
// Build labels for canonical functions 1 to novars
if b_size < a_size then
for i := 0 to b_size-1 do CanLabels[i] := 'CanVar' + IntToStr(i+1)
else for i := 0 to a_size-1 do CanLabels[i] := 'CanVar' + IntToStr(i+1);
for i := 0 to a_size - 1 do // identify left variables
begin
a_vars[i] := Labels[i];
selected[i] := GridPlace[i];
end;
for i := 0 to b_size - 1 do // identify right variables
begin
b_vars[i] := Labels[NLeft+i];
selected[NLeft+i] := GridPlace[NLeft+i];
end;
AReport.Add('CANONICAL CORRELATION ANALYSIS');
AReport.Add('');
count := NoCases;
// Get means, standard deviations, etc. for total matrix
IER := DynCorrelations(novars,selected,datagrid,bigmat,mean,variance,stddev,totalobs,3);
if (IER = 1) then
begin
ErrorMsg('Zero variance found for a variable-terminating');
exit;
end;
//partition matrix into quadrants
for i := 0 to a_size - 1 do
for j := 0 to a_size - 1 do raa[i,j]:= bigmat[i,j];
for i := a_size to novars - 1 do
for j := a_size to novars - 1 do
rbb[i-a_size,j-a_size] := bigmat[i,j];
for i := 0 to a_size - 1 do
for j := a_size to novars - 1 do
rab[i,j-a_size] := bigmat[i,j];
for i := a_size to novars - 1 do
for j := 0 to a_size - 1 do
rba[i-a_size,j] := bigmat[i,j];
if CorsChk.Checked then
begin
title := 'Left Correlation Matrix';
MatPrint(raa, NLeft, NLeft, title, a_vars, a_vars, totalobs, AReport);
title := 'Right Correlation Matrix';
MatPrint(rbb, NRight, NRight, title, b_vars, b_vars, totalobs, AReport);
title := 'Left-Right Correlation Matrix';
MatPrint(rab, NLeft, NRight, title, a_vars, b_vars, totalobs, AReport);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
end;
// get inverses of left and right hand matrices raa and rbb
for i := 0 to a_size-1 do
for j := 0 to a_size-1 do
tempmat[i,j] := raa[i,j];
SVDInverse(tempmat,a_size);
for i := 0 to a_size-1 do
for j := 0 to a_size-1 do raainv[i,j] := tempmat[i,j];
if CorsChk.Checked then
begin
title := 'Inverse of Left Matrix';
MatPrint(raainv, a_size, a_size, title, a_vars, a_vars, totalobs, AReport);
end;
for i := 0 to b_size-1 do
for j := 0 to b_size-1 do
tempmat[i,j] := rbb[i,j]; // inverse uses 1 offset
SVDInverse(tempmat,b_size);
for i := 0 to b_size-1 do // reset to 0 offset
for j := 0 to b_size - 1 do rbbinv[i,j] := tempmat[i,j];
if CorsChk.Checked then
begin
title := 'Inverse of Right Matrix';
MatPrint(rbbinv, b_size, b_size, title, b_vars, b_vars, totalobs, AReport);
end;
// get products of raainv x rab and the rbbinv x rba matrix
for i := 0 to b_size-1 do
for j := 0 to a_size-1 do first_prod[i,j] := 0.0;
MatAxB(first_prod,rbbinv,rba,b_size,b_size,b_size,a_size,errorcode);
for i := 0 to a_size-1 do
for j := 0 to b_size-1 do second_prod[i,j] := 0.0;
MatAxB(second_prod,raainv,rab,a_size,a_size,a_size,b_size,errorcode);
title := 'Right Inverse x Right-Left Matrix';
MatPrint(first_prod, b_size, a_size, title, b_vars, a_vars, totalobs, AReport);
title := 'Left Inverse x Left-Right Matrix';
MatPrint(second_prod, a_size, b_size, title, a_vars, b_vars, totalobs, AReport);
//get characteristic equations matrix (product of last two product matrices
//The product should yeild rows and cols representing the smaller of the two sets
for i := 0 to b_size-1 do
for j := 0 to b_size - 1 do char_equation[i,j] := 0.0;
MatAxB(char_equation,first_prod,second_prod,b_size,a_size,a_size,b_size,errorcode);
title := 'Canonical Function';
MatPrint(char_equation, b_size, b_size, title, CanLabels, CanLabels, totalobs, AReport);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
// now get roots and vectors of the characteristic equation using
// NonSymRoots routine
minroot := 0.0;
for i := 0 to b_size - 1 do
begin
roots[i] := 0.0;
pcnt_trace[i] := 0.0;
for j := 0 to b_size - 1 do eigenvectors[i,j] := 0.0;
end;
trace := 0.0;
no_factors := b_size;
Dynnonsymroots(char_equation, b_size, no_factors, minroot, eigenvectors, roots,
pcnt_trace, trace, pcnt_extracted);
AReport.Add('Trace of the matrix: %10.4f', [trace]);
AReport.Add('Percent of trace extracted: %10.4f', [pcnt_extracted]);
// Normalize smaller set weights and coumpute larger set weights
for i := 0 to b_size - 1 do // transpose eigenvectors
for j := 0 to b_size - 1 do eigentrans[j,i] := eigenvectors[i,j];
for i := 0 to b_size - 1 do
for j := 0 to b_size-1 do tempmat[i,j] := 0.0;
MatAxB(tempmat,eigentrans,rbb,b_size,b_size,b_size,b_size,errorcode);
for i := 0 to b_size-1 do
for j := 0 to b_size-1 do theta[i,j] := 0.0;
MatAxB(theta,tempmat,eigenvectors,b_size,b_size,b_size,b_size,errorcode);
for j := 0 to b_size - 1 do
begin
q := 1.0 / sqrt(theta[j,j]);
for i := 0 to b_size - 1 do
begin
norm_b[i,j] := eigenvectors[i,j] * q;
raw_b[i,j] := norm_b[i,j] / stddev[a_size+i];
end;
end;
for i := 0 to a_size - 1 do
for j := 0 to b_size - 1 do norm_a[i,j] := 0.0;
MatAxB(norm_a,second_prod,norm_b,a_size,b_size,b_size,b_size,errorcode);
for j := 0 to b_size-1 do
begin
for i := 0 to a_size-1 do
begin
norm_a[i,j] := norm_a[i,j] * (1.0 / sqrt(roots[j]));
raw_a[i,j] := norm_a[i,j] / stddev[i];
end;
end;
// Compute the correlations between variables and canonical variables
for i := 0 to a_size-1 do
for j := 0 to b_size-1 do a_cors[i,j] := 0.0;
MatAxB(a_cors,raa,norm_a,a_size,a_size,a_size,b_size,errorcode);
for j := 0 to b_size-1 do
begin
q := 0.0;
for i := 0 to a_size-1 do q := q + norm_a[i,j] * a_cors[i,j];
q := 1.0 / sqrt(q);
for i := 0 to a_size-1 do a_cors[i,j] := a_cors[i,j] * q;
end;
for i := 0 to b_size-1 do
for j := 0 to b_size-1 do b_cors[i,j] := 0.0;
MatAxB(b_cors,rbb,norm_b,b_size,b_size,b_size,b_size,errorcode);
for j := 0 to b_size-1 do
begin
q := 0.0;
for i := 0 to b_size-1 do q := q + norm_b[i,j] * b_cors[i,j];
q := 1.0 / sqrt(q);
for i := 0 to b_size-1 do b_cors[i,j] := b_cors[i,j] * q;
end;
// Compute the Proportions of Variance (PVs) and Redundancy Coefficients
for j := 0 to b_size-1 do
begin
pv_a[j] := 0.0;
for i := 0 to a_size-1 do pv_a[j] := pv_a[j] + (a_cors[i,j] * a_cors[i,j]);
pv_a[j] := pv_a[j] / a_size;
rd_a[j] := pv_a[j] * roots[j];
end;
for j := 0 to b_size-1 do
begin
pv_b[j] := 0.0;
for i := 0 to b_size-1 do pv_b[j] := pv_b[j] + (b_cors[i,j] * b_cors[i,j]);
pv_b[j] := pv_b[j] / b_size;
rd_b[j] := pv_b[j] * roots[j];
end;
// Compute tests of the roots
q := a_size + b_size + 1;
q := -(count - 1.0 - (q / 2.0));
k := 0;
for i := 0 to b_size-1 do
begin
w := 1.0;
for j := i to b_size-1 do w := w * (1.0 - roots[j]);
root_chi[i] := q * ln(w);
root_df[i] := (a_size - i) * (b_size - i);
chi_prob[i] := 1.0 - chisquaredprob(root_chi[i],root_df[i]);
if (chi_prob[i] < critical_prob) then k := k + 1;
end;
Roys := roots[1] / (1.0 - roots[1]);
Lambda := 1.0;
for i := 0 to b_size-1 do
begin
Hroot := roots[i] / (1.0 - roots[i]);
Lambda := Lambda * (1.0 / (1.0 + Hroot));
Pillia := Pillia + (Hroot / (1.0 + Hroot));
HLTrace := HLTrace + Hroot;
end;
// Print remaining results
AReport.Add('');
AReport.Add('');
AReport.Add(' Canonical R Root % Trace Chi-Sqr D.F. Prob.');
for i := 0 to b_size-1 do
AReport.Add('%2d %10.6f %8.3f %7.3f %8.3f %2d %8.3f',
[i+1, sqrt(roots[i]), roots[i], pcnt_trace[i], root_chi[i], root_df[i], chi_prob[i]]);
chisqr := -ln(Lambda) * (count - 1.0 - 0.5 * (a_size + b_size - 1.0));
chiprob := 1.0 - chisquaredprob(chisqr,a_size * b_size);
AReport.Add('');
AReport.Add('Overall Tests of Significance:');
AReport.Add(' Statistic Approx. Stat. Value D.F. Prob.>Value');
AReport.Add('Wilk''s Lambda Chi-Squared %10.4f %3d %6.4f', [chisqr,a_size * b_size,chiprob]);
s := b_size;
m := 0.5 * (a_size - b_size - 1);
n := 0.5 * (count - b_size - a_size - 2);
f := (HLTrace * 2.0 * (s * n + 1)) / (s * s * (2.0 * m + s + 1.0));
df1 := s * (2.0 * m + s + 1.0);
df2 := 2.0 * ( s * n + 1.0);
ftestprob := probf(f,df1,df2);
AReport.Add('Hotelling-Lawley Trace F-Test %10.4f %2.0f %2.0f %6.4f', [f, df1, df2, ftestprob]);
df2 := s * (2.0 * n + s + 1.0);
f := (Pillia / (s - Pillia)) * ( (2.0 * n + s +1.0) / (2.0 * m + s + 1.0) );
ftestprob := probf(f,df1,df2);
AReport.Add('Pillai Trace F-Test %10.4f %2.0f %2.0f %6.4f', [f, df1, df2, ftestprob]);
Roys := Roys * (count - 1 - a_size + b_size)/ a_size ;
df1 := a_size;
df2 := count - 1 - a_size + b_size;
ftestprob := probf(Roys,df1,df2);
AReport.Add('Roys Largest Root F-Test %10.4f %2.0f %2.0f %6.4f', [Roys, df1, df2, ftestprob]);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
if CorsChk.Checked then
begin
title := 'Eigenvectors';
MatPrint(eigenvectors, b_size, b_size, title, CanLabels, CanLabels, totalobs, AReport);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
end;
title := 'Standardized Right Side Weights';
MatPrint(norm_a, a_size, b_size, title, RowLabels, CanLabels, totalobs, AReport);
title := 'Standardized Left Side Weights';
MatPrint(norm_b, b_size, b_size, title, ColLabels, CanLabels, totalobs, AReport);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
title := 'Raw Right Side Weights';
MatPrint(raw_a, a_size, b_size, title, RowLabels, CanLabels, totalobs, AReport);
title := 'Raw Left Side Weights';
MatPrint(raw_b, b_size, b_size, title, ColLabels, CanLabels, totalobs, AReport);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
title := 'Right Side Correlations with Function';
MatPrint(a_cors, a_size, b_size, title, RowLabels, CanLabels, totalobs, AReport);
title := 'Left Side Correlations with Function';
MatPrint(b_cors, b_size, b_size, title, ColLabels, CanLabels, totalobs, AReport);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
if CorsChk.Checked then
begin
AReport.Add('Redundancy Analysis for Right Side Variables');
AReport.Add('');
AReport.Add(' Variance Prop. Redundancy');
for i := 0 to b_size-1 do
AReport.Add('%10d %10.5f %10.5f', [i, pv_a[i], rd_a[i]]);
AReport.Add('');
AReport.Add('Redundancy Analysis for Left Side Variables');
AReport.Add(' Variance Prop. Redundancy');
for i := 0 to b_size-1 do
AReport.Add('%10d %10.5f %10.5f', [i, pv_b[i], rd_b[i]]);
AReport.Add('');
AReport.Add(DIVIDER);
AReport.Add('');
end;
//------------- Now, clean up memory mess ----------------------------
selected := nil;
ColLabels := nil;
RowLabels := nil;
CanLabels := nil;
b_vars := nil;
a_vars := nil;
root_df := nil;
pcnt_trace := nil;
rd_b := nil;
rd_a := nil;
pv_b := nil;
pv_a := nil;
chi_prob := nil;
root_chi := nil;
roots := nil;
stddev := nil;
variance := nil;
mean := nil;
tempmat := nil;
theta := nil;
eigentrans := nil;
b_cors := nil;
a_cors := nil;
raw_b := nil;
raw_a := nil;
norm_b := nil;
norm_a := nil;
eigenvectors := nil;
rbbinv := nil;
raainv := nil;
char_equation := nil;
second_prod := nil;
first_prod := nil;
bigmat := nil;
rba := nil;
rab := nil;
rbb := nil;
raa := nil;
end;
procedure TGLMFrm.UpdateBtnStates;
begin
ContDepInBtn.Enabled := VarList.ItemIndex > -1;
ContDepOutBtn.Enabled := DepContList.ItemIndex > -1;
CatDepInBtn.Enabled := VarList.ItemIndex > -1;
CatDepOutBtn.Enabled := DepCatList.ItemIndex > -1;
ReptDepInBtn.Enabled := AnySelected(VarList);
ReptDepOutBtn.Enabled := RepeatList.ItemIndex > -1;
FixedIndepInBtn.Enabled := AnySelected(VarList);
FixedIndepOutBtn.Enabled := FixedList.ItemIndex > -1;
RndIndepInBtn.Enabled := VarList.ItemIndex > -1;
RndIndepOutBtn.Enabled := RandomList.ItemIndex > -1;
CovInBtn.Enabled := VarList.ItemIndex > -1;
CovOutBtn.Enabled := CovariateList.ItemIndex > -1;
end;
initialization
{$I glmunit.lrs}
end.