LazStats: More refactoring of WLSUnit.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7776 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-10-12 21:53:18 +00:00
parent 27d63f9c58
commit 9013e01332
4 changed files with 237 additions and 150 deletions

View File

@ -142,44 +142,38 @@ inherited WLSFrm: TWLSFrm
ParentColor = False
end
object Label2: TLabel[7]
AnchorSideLeft.Control = DepInBtn
AnchorSideLeft.Side = asrBottom
AnchorSideLeft.Control = DepVarEdit
AnchorSideBottom.Control = DepVarEdit
Left = 157
Left = 161
Height = 15
Top = 21
Width = 102
Anchors = [akLeft, akBottom]
BorderSpacing.Left = 4
BorderSpacing.Top = 8
BorderSpacing.Bottom = 2
Caption = 'Dependent Variable'
ParentColor = False
end
object Label3: TLabel[8]
AnchorSideLeft.Control = IndInBtn
AnchorSideLeft.Side = asrBottom
AnchorSideLeft.Control = IndVarList
AnchorSideTop.Control = IndInBtn
Left = 157
Left = 161
Height = 15
Top = 105
Width = 116
BorderSpacing.Left = 4
Caption = 'Independent Variables'
ParentColor = False
end
object Label4: TLabel[9]
AnchorSideLeft.Control = WeightInBtn
AnchorSideLeft.Side = asrBottom
AnchorSideLeft.Control = WeightVarEdit
AnchorSideBottom.Control = WeightVarEdit
Left = 157
Left = 161
Height = 15
Top = 205
Width = 134
Width = 77
Anchors = [akLeft, akBottom]
BorderSpacing.Left = 4
BorderSpacing.Bottom = 2
Caption = 'User''s Weights (Optional)'
Caption = 'User''s Weights'
Enabled = False
ParentColor = False
end
@ -192,10 +186,10 @@ inherited WLSFrm: TWLSFrm
Left = 0
Height = 240
Top = 17
Width = 123
Width = 119
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Top = 2
BorderSpacing.Right = 4
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
Constraints.MinHeight = 220
ItemHeight = 0
@ -306,12 +300,12 @@ inherited WLSFrm: TWLSFrm
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = DepOutBtn
AnchorSideBottom.Side = asrBottom
Left = 157
Left = 161
Height = 23
Top = 38
Width = 123
Width = 119
Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 4
BorderSpacing.Left = 8
BorderSpacing.Bottom = 12
ReadOnly = True
TabOrder = 3
@ -325,12 +319,12 @@ inherited WLSFrm: TWLSFrm
AnchorSideRight.Control = ParamsPanel
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = WeightInBtn
Left = 157
Left = 161
Height = 63
Top = 122
Width = 123
Width = 119
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Left = 4
BorderSpacing.Left = 8
BorderSpacing.Top = 2
BorderSpacing.Bottom = 16
ItemHeight = 0
@ -346,12 +340,12 @@ inherited WLSFrm: TWLSFrm
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = WeightOutBtn
AnchorSideBottom.Side = asrBottom
Left = 157
Left = 161
Height = 23
Top = 222
Width = 123
Width = 119
Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 4
BorderSpacing.Left = 8
BorderSpacing.Bottom = 12
Enabled = False
ReadOnly = True

View File

@ -58,6 +58,9 @@ type
ResidualsRegReportFrame: TReportFrame;
WLSReportFrame: TReportFrame;
procedure AddPredictedStuffToGrid(AIndepCols: IntDyneVec; ANumIndepCols: Integer;
BWeights: DblDyneVec);
procedure CreateOrGetChartFrame(AColIndex: Integer; AVarName: String;
out AMemo: TMemo; out AChartFrame: TChartFrame);
@ -77,6 +80,13 @@ type
out AIndepCols: IntDyneVec; out AWeightCol: Integer;
out ARowLabels: StrDyneVec): Boolean;
function Process_OLSRegression(AIndepCols: IntDyneVec; ANumIndepCols, ADepCol: Integer;
ARowLabels: StrDyneVec; ANumCases: Integer; PrintAll: Boolean): Boolean;
function Process_SquaredResidualsRegression(AIndepCols: IntDyneVec;
ANumIndepCols, ADepCol: Integer; ARowLabels: StrDyneVec;
BWeights: DblDyneVec; ANumCases: Integer; PrintAll: Boolean): Boolean;
procedure WriteDescriptiveReport(AMemo: TMemo;
const ARegressionResults: TBivariateRegressionResults;
const XLabel, YLabel: String);
@ -145,6 +155,50 @@ begin
end;
{ Get predicted squared residuals and save recipricols to grid as weights }
procedure TWLSFrm.AddPredictedStuffToGrid(AIndepCols: IntDyneVec;
ANumIndepCols: Integer; BWeights: DblDyneVec);
var
col: Integer;
i, j: Integer;
X, predicted: Double;
begin
col := NoVariables + 1;
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
DictionaryFrm.NewVar(col);
DictionaryFrm.DictGrid.Cells[1, col] := 'PredResid2';
OS3MainFrm.DataGrid.Cells[col, 0] := 'PredResid2';
col := NoVariables + 1;
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
DictionaryFrm.NewVar(col);
DictionaryFrm.DictGrid.Cells[1, col] := 'WEIGHT';
OS3MainFrm.DataGrid.Cells[col, 0] := 'WEIGHT';
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
for i := 1 to NoCases do
begin
if (DataProcs.ValidValue(i, col-2)) then // do we have a valid squared OLS residual?
begin
predicted := 0.0;
for j := 0 to ANumIndepCols - 1 do
begin
X := StrToFloat(OS3MainFrm.DataGrid.Cells[AIndepCols[j], i]);
predicted := predicted + BWeights[j] * X;
end;
predicted := predicted + BWeights[ANumIndepCols];
predicted := abs(predicted);
OS3MainFrm.DataGrid.Cells[col-1, i] := Format('%.3f', [predicted]);
if (predicted > 0.0) then
predicted := 1.0 / sqrt(predicted)
else
predicted := 0.0;
OS3MainFrm.DataGrid.Cells[col, i] := Format('%.3f', [predicted]);
end;
end;
end;
procedure TWLSFrm.AdjustConstraints;
begin
ParamsPanel.Constraints.MinHeight := DepInBtn.Top + (IndOutBtn.Top - DepInBtn.Top)*2 + DepInBtn.Top +
@ -158,7 +212,7 @@ end;
procedure TWLSFrm.Compute;
var
i, j, Noindep, DepCol, WghtCol, olddepcol, NCases, pos, col: integer;
i, j, noIndep, depCol, weightCol, oldDepCol, NCases, pos, col: integer;
IndepCols: IntDyneVec = nil;
RowLabels: StrDyneVec = nil;
X, Y: double;
@ -170,136 +224,49 @@ var
BStdErrs: DblDyneVec = nil;
BtTests: DblDyneVec = nil;
tProbs: DblDyneVec = nil;
PrintDesc: boolean = true;
predicted: Double;
lReport: TStrings;
StdErrEst: Double = 0.0;
R2: Double = 0.0;
errorcode: Boolean = false;
PrintDesc: boolean = true;
begin
PrintDesc := true;
SetLength(Means, NoVariables + 2);
SetLength(Variances, NoVariables + 2);
SetLength(StdDevs, NoVariables + 2);
SetLength(BWeights, NoVariables + 2);
SetLength(BWeights, NoVariables + 2); // do not remove!
SetLength(BetaWeights, NoVariables + 2);
SetLength(BStdErrs, NoVariables + 2);
SetLength(Bttests, NoVariables + 2);
SetLength(tprobs, NoVariables + 2);
// SetLength(RowLabels, NoVariables + 2);
// SetLength(IndepCols, NoVariables + 2);
// SetLength(ColNoSelected, 2);
lReport := TStringList.Create;
try
NCases := NoCases;
// NoIndep := IndVarList.Items.Count;
if not PrepareData(depCol, NoIndep, indepCols, wghtCol, RowLabels) then
// Get column indexes and do some validation checks.
// NOTE that the Length(indepCols) is different from NoIndep.
if not PrepareData(depCol, noIndep, indepCols, weightCol, RowLabels) then
exit;
{ wp: I think this is not correct: The column index is the last one in this
call. And why is row 0 checked?
// check variable types
if not ValidValue(OS3MainFrm.DataGrid, DepCol, 0) then
begin
ErrorMsg('Incorrect dependent variable type.');
exit;
end;
if (WghtCol > -1) then
begin
if not ValidValue(OS3MainFrm.DataGrid, WghtCol, 0) then
begin
ErrorMsg('Incorrect weight variable type.');
exit;
end;
end;
for j := 0 to Noindep - 1 do
begin
if not ValidValue(OS3MainFrm.DataGrid, IndepCols[j],0) then
begin
ErrorMsg('Incorrect dependent variable type.');
exit;
end;
end;
}
IndepCols[NoIndep] := depCol;
oldDepCol := DepCol; // save dependent column so we can reuse DepCol
// Save dependent column so we can re-use DepCol
oldDepCol := depCol;
// *** Get OLS regression ***
lReport.Clear;
lReport.Add('ORDINARY LEAST SQUARES (OLS) REGRESSION RESULTS');
lReport.Add('');
MReg(Noindep, IndepCols, DepCol, RowLabels, Means, Variances, StdDevs,
BWeights, BetaWeights, BStdErrs, Bttests, tprobs, R2, stderrest,
NCases, errorcode, PrintDesc, lReport);
// Get predicted z score, residual z score, predicted raw score,
// residual raw score and squared raw residual score. Place in the DataGrid
PredictIt(IndepCols, Noindep+1, Means, StdDevs, BetaWeights, stderrest, NoIndep);
OLSReportFrame.DisplayReport(lReport);
lReport.Clear;
Process_OLSRegression(indepCols, noIndep, depCol, RowLabels, nCases, printDesc);
// *** Regress the squared residuals on the predictors ***
depCol := NoVariables;
lReport.Clear;
lReport.Add('REGRESSION OF SQUARED RESIDUALS ON INDEPENDENT VARIABLES');
lReport.Add('');
MReg(Noindep, IndepCols, DepCol, RowLabels, Means, Variances, StdDevs,
BWeights, BetaWeights, BStdErrs, Bttests, tprobs, R2, stderrest,
NCases, errorcode, PrintDesc, lReport);
ResidualsRegReportFrame.DisplayReport(lReport);
lReport.Clear;
Process_SquaredResidualsRegression(indepCols, noIndep, depCol, RowLabels,
BWeights, nCases, printDesc);
if WeightChk.Checked then
begin
// Get predicted squared residuals and save recipricols as weights
col := NoVariables + 1;
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
DictionaryFrm.NewVar(col);
DictionaryFrm.DictGrid.Cells[1,col] := 'PredResid2';
OS3MainFrm.DataGrid.Cells[col,0] := 'PredResid2';
col := NoVariables + 1;
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
DictionaryFrm.NewVar(col);
DictionaryFrm.DictGrid.Cells[1,col] := 'WEIGHT';
OS3MainFrm.DataGrid.Cells[col,0] := 'WEIGHT';
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
for i := 1 to NoCases do
begin
if (DataProcs.ValidValue(i, col-2)) then // do we have a valid squared OLS residual?
begin
predicted := 0.0;
for j := 0 to NoIndep - 1 do
begin
pos := IndepCols[j];
X := StrToFloat(OS3MainFrm.DataGrid.Cells[pos,i]);
predicted := predicted + BWeights[j] * X;
end;
predicted := predicted + BWeights[Noindep];
predicted := abs(predicted);
OS3MainFrm.DataGrid.Cells[col-1,i] := Format('%.3f', [predicted]);
if (predicted > 0.0) then
predicted := 1.0 / sqrt(predicted)
else
predicted := 0.0;
OS3MainFrm.DataGrid.Cells[col,i] := Format('%.3f', [predicted]);
end; // if valid case
end; // next i
end; // if regresChk
AddPredictedStuffToGrid(indepCols, noIndep, BWeights);
// *** Display squared residuals for each independent variable ***
PlotSquaredResiduals(IndepCols, NoIndep, DepCol, 0.95);
// NOTE: depCol points to the squared residuals column here
PlotSquaredResiduals(IndepCols, NoIndep, depCol, 0.95);
if not UserWeightsChk.Checked then
if WeightChk.Checked then
begin
// Weight variables and do OLS regression on weighted variables
DepCol := olddepcol;
@ -312,7 +279,7 @@ begin
pos := IndepCols[j];
X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[pos,i]));
X := X * Y;
OS3MainFrm.DataGrid.Cells[pos,i] := FloatToStr(X);
OS3MainFrm.DataGrid.Cells[pos,i] := FloatToStr(X); // wp: DON'T OVERWRITE GRID CELLS
end;
end;
@ -339,7 +306,7 @@ begin
begin
X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[pos,i]));
X := X - Means[j];
OS3MainFrm.DataGrid.Cells[pos,i] := FloatToStr(X);
OS3MainFrm.DataGrid.Cells[pos,i] := FloatToStr(X); // wp: DON'T OVERWRITE GRID DATA!
end;
end; // next i
end; // next j
@ -349,25 +316,25 @@ begin
lReport.Add('WEIGHTED LEAST SQUARES (WLS) REGRESSION RESULTS');
lReport.Add('');
MReg(Noindep, IndepCols, DepCol, RowLabels, Means, Variances, StdDevs,
BWeights, BetaWeights, BStdErrs, Bttests, tprobs, R2, stderrest,
BWeights, BetaWeights, BStdErrs, Bttests, tprobs, R2, stdErrEst,
NCases, errorcode, PrintDesc, lReport);
WLSReportFrame.DisplayReport(lReport);
lReport.Clear;
end // if useweightschk checked
else
end; // if weightschk checked
// use the weights entered by the user
if (UserWeightsChk.Checked) then
if UserWeightsChk.Checked then
begin
// Weight variables and do OLS regression on weighted variables
DepCol := olddepcol;
IndepCols[Noindep] := DepCol;
depCol := olddepcol;
indepCols[Noindep] := depCol; // wp: CALCULATION SHOULD NORMALIZE USER WEIGHTS HERE !!!
for i := 1 to NoCases do
begin
Y := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[WghtCol,i])); // weight
Y := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[weightCol,i])); // weight
for j := 0 to Noindep do
begin
pos := IndepCols[j];
pos := indepCols[j];
X := StrToFloat(OS3MainFrm.DataGrid.Cells[pos,i]);
X := X * Y;
OS3MainFrm.DataGrid.Cells[pos,i] := FloatToStr(X);
@ -395,7 +362,7 @@ begin
begin
X := StrToFloat(OS3MainFrm.DataGrid.Cells[pos,i]);
X := X - Means[j];
OS3MainFrm.DataGrid.Cells[pos,i] := FloatToStr(X);
OS3MainFrm.DataGrid.Cells[pos,i] := FloatToStr(X); // wp: DON'T OVERWRITE GRID DATA!
end;
end; // next i
end; // next j
@ -405,7 +372,7 @@ begin
lReport.Add('WEIGHTED LEAST SQUARES (WLS) REGRESSION RESULTS');
lReport.Add('');
MReg(Noindep, IndepCols, DepCol, RowLabels, Means, Variances, StdDevs,
BWeights, BetaWeights, BStdErrs, Bttests, tprobs, R2, stderrest,
BWeights, BetaWeights, BStdErrs, Bttests, tprobs, R2, stdErrEst,
NCases, errorcode, PrintDesc, lReport);
WLSReportFrame.DisplayReport(lReport);
@ -689,7 +656,6 @@ var
predicted, zpredicted, z1, z2, resid, residsqr: double;
begin
col := NoVariables + 1;
// NoVariables := col;
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
DictionaryFrm.DictGrid.ColCount := 8;
DictionaryFrm.NewVar(col);
@ -697,7 +663,6 @@ begin
DictionaryFrm.DictGrid.Cells[1,col] := 'Pred.z';
col := NoVariables + 1;
// NoVariables := col;
DictionaryFrm.NewVar(col);
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
OS3MainFrm.DataGrid.Cells[col,0] := 'z Resid.';
@ -761,7 +726,7 @@ begin
begin
residsqr := StrToFloat(OS3MainFrm.DataGrid.Cells[col-1,i]);
residsqr := residsqr * residsqr;
OS3MainFrm.DataGrid.Cells[col,i] := Format('%8.3f',[residsqr]);
OS3MainFrm.DataGrid.Cells[col,i] := Format('%.3f',[residsqr]);
end;
end;
@ -807,10 +772,124 @@ begin
ARowLabels[i] := IndVarList.Items[i];
end;
// Append dependent column index to the independent columns vector.
AIndepCols[ANumIndepCols] := ADepCol;
// Check variable types: all of them must be numeric (float or integer)
if not IsNumericCol(ADepCol) then
begin
ErrorMsg('Incorrect data type of dependent variable.');
exit;
end;
for i := 0 to ANumIndepCols-1 do
if not IsNumericCol(AIndepCols[i]) then
begin
ErrorMsg('Incorrect data type of independent variable "%s"', [ARowLabels[i]]);
exit;
end;
if (AWeightCol > -1) and (not IsNumericCol(AWeightCol)) then
begin
ErrorMsg('Incorrect data type of weight variable.');
exit;
end;
Result := true;
end;
{ Runs the ordinary least squares regression on the grid data }
function TWLSFrm.Process_OLSRegression(AIndepCols: IntDyneVec; ANumIndepCols, ADepCol: Integer;
ARowLabels: StrDyneVec; ANumCases: Integer; PrintAll: Boolean): Boolean;
var
lReport: TStrings;
means: DblDyneVec = nil;
variances: DblDyneVec = nil;
stdDevs: DblDyneVec = nil;
BWeights: DblDyneVec = nil;
BetaWeights: DblDyneVec = nil;
BStdErrs: DblDyneVec = nil;
BtTests: DblDyneVec = nil;
tProbs: DblDyneVec = nil;
R2, stdErrEst: Double;
error: Boolean;
begin
Result := false;
lReport := TStringList.Create;
try
lReport.Add('ORDINARY LEAST SQUARES (OLS) REGRESSION RESULTS');
lReport.Add('');
SetLength(means, NoVariables + 2);
SetLength(variances, NoVariables + 2);
SetLength(stdDevs, NoVariables + 2);
SetLength(BWeights, NoVariables + 2);
SetLength(BetaWeights, NoVariables + 2);
SetLength(BStdErrs, NoVariables + 2);
SetLength(Bttests, NoVariables + 2);
SetLength(tprobs, NoVariables + 2);
MReg(ANumIndepCols, AIndepCols, ADepCol, ARowLabels, Means, Variances, StdDevs,
BWeights, BetaWeights, BStdErrs, Bttests, tprobs, R2, stdErrEst,
ANumCases, error, PrintAll, lReport);
// if error then // wp: Why does MReg exit with error???
// exit;
// Get predicted z score, residual z score, predicted raw score,
// residual raw score and squared raw residual score. Place in the DataGrid
PredictIt(AIndepCols, ANumIndepCols+1, means, stdDevs, BetaWeights, stdErrEst, ANumIndepCols);
OLSReportFrame.DisplayReport(lReport);
Result := true;
finally
lReport.Free;
end;
end;
function TWLSFrm.Process_SquaredResidualsRegression(AIndepCols: IntDyneVec;
ANumIndepCols, ADepCol: Integer; ARowLabels: StrDyneVec; BWeights: DblDyneVec;
ANumCases: Integer; PrintAll: Boolean): Boolean;
var
lReport: TStrings;
means: DblDyneVec = nil;
variances: DblDyneVec = nil;
stdDevs: DblDyneVec = nil;
BetaWeights: DblDyneVec = nil;
BStdErrs: DblDyneVec = nil;
BtTests: DblDyneVec = nil;
tProbs: DblDyneVec = nil;
R2, stdErrEst: Double;
error: Boolean;
begin
lReport := TStringList.Create;
try
lReport.Add('REGRESSION OF SQUARED RESIDUALS ON INDEPENDENT VARIABLES');
lReport.Add('');
SetLength(means, NoVariables + 2);
SetLength(variances, NoVariables + 2);
SetLength(stdDevs, NoVariables + 2);
SetLength(BetaWeights, NoVariables + 2);
SetLength(BStdErrs, NoVariables + 2);
SetLength(Bttests, NoVariables + 2);
SetLength(tprobs, NoVariables + 2);
MReg(ANumIndepCols, AIndepCols, ADepCol, ARowLabels, Means, Variances, StdDevs,
BWeights, BetaWeights, BStdErrs, Bttests, tprobs, R2, stdErrEst,
ANumCases, error, PrintAll, lReport);
ResidualsRegReportFrame.DisplayReport(lReport);
finally
lReport.Free;
end;
end;
procedure TWLSFrm.Reset;
var
i: integer;

View File

@ -25,6 +25,8 @@ function IsFiltered(AGrid: TStringGrid; ARow: integer): boolean;
function IsMissingValueCode(AGrid: TStringGrid; ARow, ACol: Integer): Boolean;
function IsNumericCol(AColIndex: Integer): Boolean;
function ValidValue(AGrid: TStringGrid; ARow, ACol: integer): boolean;
@ -155,6 +157,17 @@ begin
end;
{ Checks in the dictionary whether the variable in the specified grid column has
either data type float or integer. }
function IsNumericCol(AColIndex: Integer): Boolean;
var
typeCode: String;
begin
typeCode := Trim(DictionaryFrm.DictGrid.Cells[4, AColIndex]);
Result := (typeCode = 'F') or (typeCode = 'I');
end;
{ Checks wheter the value in cell at the given column and row is a not-filtered,
non-empty number.
NOTE: non-numeric characters in a numeric field are not taken into account! }

View File

@ -53,7 +53,7 @@ procedure EffectCode(GridCol, min, max : integer;
procedure MReg(NoIndep: integer; const IndepCols: IntDyneVec; DepCol: integer;
const RowLabels: StrDyneVec;
const Means, Variances, StdDevs, BWeights, BetaWeights, BStdErrs, Bttests, tProbs: DblDyneVec;
out R2, StdErrEst: double; out NCases: integer; out ErrorCode: boolean;
out R2, StdErrEst: double; NCases: integer; out ErrorCode: boolean;
PrintAll: boolean; AReport: TStrings);
procedure Dynnonsymroots(var a : DblDyneMat; nv : integer;
@ -347,16 +347,14 @@ begin
end;
//-------------------------------------------------------------------
// Product of matrix b times c with results returned in a
// Product of matrix B times C with results returned in a: A = B C
procedure MatAxB(const A, B, C: DblDyneMat; BRows, BCols, CRows, CCols: Integer;
out ErrorCode: boolean);
var
i, j, k: integer;
begin
ErrorCode := false;
if (BCols <> CRows) then
ErrorCode := true
else
ErrorCode := BCols <> CRows;
if not ErrorCode then
begin
for i := 0 to BRows-1 do
begin
@ -633,7 +631,7 @@ end;
Variances ... Variance of each independent variable
StdDevs ..... Standard deviations of each independent variable
NCases ...... Count of valid cases found in the grid
NCases ...... Count valid cases in the grid
ErrorCode ... if true, an error has occured during the calculations
PrintAll .... if true, intermediate matrices and vectors are written to the report
AReport ..... a string list to which the report is written.
@ -641,7 +639,7 @@ end;
procedure MReg(NoIndep: integer; const IndepCols: IntDyneVec; DepCol: integer;
const RowLabels: StrDyneVec;
const Means, Variances, StdDevs, BWeights, BetaWeights, BStdErrs, Bttests, tProbs: DblDyneVec;
out R2, StdErrEst: double; out NCases: integer; out ErrorCode: boolean;
out R2, StdErrEst: double; NCases: integer; out ErrorCode: boolean;
PrintAll: boolean; AReport: TStrings);
var
i, j, N: integer;
@ -751,6 +749,9 @@ begin
// get product of the augmented X transpose times augmented X
MatAXB(XTX, XT, X, NoIndep+1, NCases, NCases, NoIndep+1, errorcode);
if errorCode then
exit;
if PrintAll then
begin
title := 'XTX MATRIX';