From 9013e013328fd6862c7093a32888a6b0f571b49b Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Mon, 12 Oct 2020 21:53:18 +0000 Subject: [PATCH] LazStats: More refactoring of WLSUnit. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7776 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../analysis/multiple_regression/wlsunit.lfm | 44 ++- .../analysis/multiple_regression/wlsunit.pas | 313 +++++++++++------- .../lazstats/source/units/gridprocs.pas | 13 + .../lazstats/source/units/matrixlib.pas | 17 +- 4 files changed, 237 insertions(+), 150 deletions(-) diff --git a/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.lfm b/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.lfm index 194dbf15b..59ab55183 100644 --- a/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.lfm +++ b/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.lfm @@ -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 diff --git a/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.pas b/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.pas index 7f7015c3f..d1b65434f 100644 --- a/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.pas +++ b/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.pas @@ -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; diff --git a/applications/lazstats/source/units/gridprocs.pas b/applications/lazstats/source/units/gridprocs.pas index b4b923843..2a6a22263 100644 --- a/applications/lazstats/source/units/gridprocs.pas +++ b/applications/lazstats/source/units/gridprocs.pas @@ -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! } diff --git a/applications/lazstats/source/units/matrixlib.pas b/applications/lazstats/source/units/matrixlib.pas index 6e38ff750..8c4a1ff24 100644 --- a/applications/lazstats/source/units/matrixlib.pas +++ b/applications/lazstats/source/units/matrixlib.pas @@ -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';