diff --git a/applications/lazstats/source/forms/analysis/multiple_regression/lsmrunit.lfm b/applications/lazstats/source/forms/analysis/multiple_regression/lsmrunit.lfm index 3a354d2ea..5ba525f41 100644 --- a/applications/lazstats/source/forms/analysis/multiple_regression/lsmrunit.lfm +++ b/applications/lazstats/source/forms/analysis/multiple_regression/lsmrunit.lfm @@ -127,9 +127,9 @@ inherited LSMregForm: TLSMregForm Left = 0 Height = 15 Top = 232 - Width = 163 + Width = 192 BorderSpacing.Right = 8 - Caption = 'Minimum Prob. to enter block:' + Caption = 'Minimum probability to enter block:' ParentColor = False end object OptionsGroup: TGroupBox[12] @@ -194,7 +194,7 @@ inherited LSMregForm: TLSMregForm Caption = 'Show Variances' TabOrder = 4 end - object SDChkBox: TCheckBox + object StdDevChkBox: TCheckBox Left = 190 Height = 19 Top = 48 @@ -295,7 +295,7 @@ inherited LSMregForm: TLSMregForm AnchorSideLeft.Side = asrBottom AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = OptionsGroup - Left = 171 + Left = 200 Height = 23 Top = 228 Width = 50 @@ -326,7 +326,36 @@ inherited LSMregForm: TLSMregForm Left = 413 Height = 430 end - object SaveDialog: TSaveDialog[2] + object PageControl: TPageControl[2] + Left = 422 + Height = 414 + Top = 8 + Width = 580 + ActivePage = MeanVarStddevPage + Align = alClient + BorderSpacing.Left = 4 + BorderSpacing.Top = 8 + BorderSpacing.Right = 8 + BorderSpacing.Bottom = 8 + TabIndex = 4 + TabOrder = 2 + object RegressionPage: TTabSheet + Caption = 'Regression' + end + object CrossProductsPage: TTabSheet + Caption = 'Cross-Products Matrix' + end + object VarCovarPage: TTabSheet + Caption = 'Variance-Covariance' + end + object CorrelationsPage: TTabSheet + Caption = 'Correlations' + end + object MeanVarStddevPage: TTabSheet + Caption = 'MeanVarStdDev' + end + end + object SaveDialog: TSaveDialog[3] Left = 45 Top = 357 end diff --git a/applications/lazstats/source/forms/analysis/multiple_regression/lsmrunit.pas b/applications/lazstats/source/forms/analysis/multiple_regression/lsmrunit.pas index be693018c..1ceac5ced 100644 --- a/applications/lazstats/source/forms/analysis/multiple_regression/lsmrunit.pas +++ b/applications/lazstats/source/forms/analysis/multiple_regression/lsmrunit.pas @@ -6,14 +6,14 @@ interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, - StdCtrls, Buttons, ExtCtrls, Globals, MainUnit, MatrixLib, - DataProcs, DictionaryUnit, BasicStatsReportFormUnit; + StdCtrls, Buttons, ExtCtrls, ComCtrls, Globals, MainUnit, MatrixLib, + DataProcs, DictionaryUnit, BasicStatsParamsFormUnit, ReportFrameUnit; type { TLSMregForm } - TLSMregForm = class(TBasicStatsReportForm) + TLSMregForm = class(TBasicStatsParamsForm) AllBtn: TBitBtn; IndepVars: TListBox; CorrsChkBox: TCheckBox; @@ -31,10 +31,16 @@ type Label5: TLabel; MatSaveChkBox: TCheckBox; MeansChkBox: TCheckBox; + PageControl: TPageControl; SaveDialog: TSaveDialog; OutBtn: TBitBtn; PredictChkBox: TCheckBox; - SDChkBox: TCheckBox; + StdDevChkBox: TCheckBox; + RegressionPage: TTabSheet; + CrossProductsPage: TTabSheet; + CorrelationsPage: TTabSheet; + MeanVarStddevPage: TTabSheet; + VarCovarPage: TTabSheet; VarChkBox: TCheckBox; VarList: TListBox; procedure AllBtnClick(Sender: TObject); @@ -47,14 +53,21 @@ type procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean); private { private declarations } + FRegressionFrame: TReportFrame; + FCrossProductsFrame: TReportFrame; + FCorrelationsFrame: TReportFrame; + FVarCovarFrame: TReportFrame; + FMeanVarStddevFrame: TReportFrame; IndepVarsCols: IntDyneVec; NoVars: integer; NoBlocks: integer; + procedure HideTabs; protected procedure AdjustConstraints; override; procedure Compute; override; procedure UpdateBtnStates; override; public + constructor Create(AOwner: TComponent); override; procedure Reset; override; end; @@ -73,6 +86,64 @@ uses { TLSMregForm } +constructor TLSMregForm.Create(AOwner: TComponent); +begin + inherited; + + FRegressionFrame := TReportFrame.Create(self); + FRegressionFrame.Name := ''; + FRegressionFrame.Parent := RegressionPage; + FRegressionFrame.Align := alClient; + FRegressionFrame.BorderSpacing.Left := 0; + FRegressionFrame.BorderSpacing.Top := 0; + FRegressionFrame.BorderSpacing.Bottom := 0; + FRegressionFrame.BorderSpacing.Right := 0; + InitToolbar(FRegressionFrame.ReportToolbar, tpRight); + + FCrossProductsFrame := TReportFrame.Create(self); + FCrossProductsFrame.Name := ''; + FCrossProductsFrame.Parent := CrossProductsPage; + FCrossProductsFrame.Align := alClient; + FCrossProductsFrame.BorderSpacing.Left := 0; + FCrossProductsFrame.BorderSpacing.Top := 0; + FCrossProductsFrame.BorderSpacing.Bottom := 0; + FCrossProductsFrame.BorderSpacing.Right := 0; + InitToolbar(FCrossProductsFrame.ReportToolbar, tpRight); + + FCorrelationsFrame := TReportFrame.Create(self); + FCorrelationsFrame.Name := ''; + FCorrelationsFrame.Parent := CorrelationsPage; + FCorrelationsFrame.Align := alClient; + FCorrelationsFrame.BorderSpacing.Left := 0; + FCorrelationsFrame.BorderSpacing.Top := 0; + FCorrelationsFrame.BorderSpacing.Bottom := 0; + FCorrelationsFrame.BorderSpacing.Right := 0; + InitToolbar(FCorrelationsFrame.ReportToolbar, tpRight); + + FVarCovarFrame := TReportFrame.Create(self); + FVarCovarFrame.Name := ''; + FVarCovarFrame.Parent := VarCovarPage; + FVarCovarFrame.Align := alClient; + FVarCovarFrame.BorderSpacing.Left := 0; + FVarCovarFrame.BorderSpacing.Top := 0; + FVarCovarFrame.BorderSpacing.Bottom := 0; + FVarCovarFrame.BorderSpacing.Right := 0; + InitToolbar(FVarCovarFrame.ReportToolbar, tpRight); + + FMeanVarStddevFrame := TReportFrame.Create(self); + FMeanVarStddevFrame.Name := ''; + FMeanVarStddevFrame.Parent := MeanVarStdDevPage; + FMeanVarStddevFrame.Align := alClient; + FMeanVarStddevFrame.BorderSpacing.Left := 0; + FMeanVarStddevFrame.BorderSpacing.Top := 0; + FMeanVarStddevFrame.BorderSpacing.Bottom := 0; + FMeanVarStddevFrame.BorderSpacing.Right := 0; + InitToolbar(FMeanVarStddevFrame.ReportToolbar, tpRight); + + PageControl.ActivePage := RegressionPage; +end; + + procedure TLSMregForm.AdjustConstraints; begin ParamsPanel.Constraints.MinWidth := Max( @@ -125,6 +196,14 @@ var errcode: boolean = false; anerror: Integer = 0; lReport: TStrings; + + procedure AddHeaderToReport; + begin + lReport.Clear; + lReport.Add('LEAST SQUARES MULTIPLE REGRESSION by Bill Miller'); + lReport.Add(''); + end; + begin NCases := NoCases; SetLength(corrs,NoVariables+1,NoVariables+1); @@ -159,8 +238,6 @@ begin lReport := TStringList.Create; try - lReport.Add('LEAST SQUARES MULTIPLE REGRESSION by Bill Miller'); - lReport.Add(''); errorcode := false; { get dependendent variable column } @@ -199,55 +276,75 @@ begin if CPChkBox.Checked then begin title := 'Cross-Products Matrix'; + AddHeaderToReport; GridXProd(NEntered, ColEntered, Corrs, errcode, NCases); MatPrint(Corrs, NEntered, NEntered, title, IndRowLabels, IndColLabels, NCases, lReport); - lReport.Add(DIVIDER_SMALL); - end; + FCrossProductsFrame.DisplayReport(lReport); + CrossProductsPage.TabVisible := true; + end else + CrossProductsPage.TabVisible := false; if CovChkBox.Checked then begin title := 'Variance-Covariance Matrix'; + AddHeaderToReport; GridCovar(NEntered,ColEntered, Corrs, Means, Variances, StdDevs, errcode, NCases); MatPrint(Corrs, NEntered, NEntered, title, IndRowLabels, IndColLabels, NCases, lReport); - lReport.Add(DIVIDER_SMALL); + FVarCovarFrame.DisplayReport(lReport); + VarCovarPage.TabVisible := true; +// lReport.Add(DIVIDER_SMALL); end; - Correlations(NEntered,ColEntered,Corrs,Means,Variances, StdDevs,errcode,NCases); + Correlations(NEntered,ColEntered,Corrs,Means,Variances, StdDevs,errcode,NCases); if CorrsChkBox.Checked then begin title := 'Product-Moment Correlations Matrix'; + AddHeaderToReport; MatPrint(Corrs, NEntered, NEntered, title, IndRowLabels, IndColLabels, NCases, lReport); - lReport.Add(DIVIDER_SMALL); - end; + FCorrelationsFrame.DisplayReport(lReport); + CorrelationsPage.TabVisible := true; + end else + CorrelationsPage.TabVisible := false; - if MeansChkBox.Checked then + if MeansChkBox.Checked or VarChkBox.Checked or StdDevChkBox.Checked then begin - title := 'Means'; - DynVectorPrint(Means, NEntered, title, IndColLabels, NCases, lReport); - lReport.Add(DIVIDER_SMALL); - end; + AddHeaderToReport; - if VarChkBox.Checked = true then - begin - title := 'Variances'; - DynVectorPrint(Variances, NEntered, title, IndColLabels, NCases, lReport); - lReport.Add(DIVIDER_SMALL); - end; + if MeansChkBox.Checked then + begin + title := 'Means'; + DynVectorPrint(Means, NEntered, title, IndColLabels, NCases, lReport); + lReport.Add(DIVIDER_SMALL); + end; - if SDChkBox.Checked = true then - begin - title := 'Standard Deviations'; - DynVectorPrint(StdDevs, NEntered, title, IndColLabels, NCases, lReport); - lReport.Add(DIVIDER_SMALL); - end; + if VarChkBox.Checked then + begin + title := 'Variances'; + DynVectorPrint(Variances, NEntered, title, IndColLabels, NCases, lReport); + lReport.Add(DIVIDER_SMALL); + end; + + if StdDevChkBox.Checked then + begin + title := 'Standard Deviations'; + DynVectorPrint(StdDevs, NEntered, title, IndColLabels, NCases, lReport); + lReport.Add(DIVIDER_SMALL); + end; + + FMeanVarStddevFrame.DisplayReport(lReport); + MeanVarStddevPage.TabVisible := true; + end else + MeanVarStddevPage.TabVisible := false; if errorcode then begin - MessageDlg('A selected variable has no variability. Run aborted.', mtError, [mbOK], 0); + ErrorMsg('A selected variable has no variability. Run aborted.'); exit; end; NoIndepVars := NEntered - 1; + AddHeaderToReport; + MReg(NoIndepVars, ColEntered, DepVarCol, IndRowLabels, Means, Variances, StdDevs, BWeights, BetaWeights, BStdErrs, Bttests, tProbs, R2, StdErrEst, NCases, errorcode, true, lReport); @@ -256,6 +353,7 @@ begin df2 := NCases - NoIndepVars - 1; F := ((R2 - OldR2) / (1.0 - R2)) * df2 / df1; FProbF := ProbF(F,df1,df2); + lReport.Add(''); if FProbF < probIn then lReport.Add('Entry requirements met') else @@ -279,9 +377,6 @@ begin BetaWeights, StdErrEst, IndepVarsCols, NoIndepVars); end; -// OutputFrm.ShowModal; -// OutputFrm.RichEdit.Clear; - if MatSaveChkBox.Checked then begin SaveDialog.Filter := 'LazStats matrix files (*.mat)|*.mat;*.MAT|All files (*.*)|*.*'; @@ -293,7 +388,7 @@ begin end; end; - FReportFrame.DisplayReport(lReport); + FRegressionFrame.DisplayReport(lReport); finally lReport.Free; @@ -358,6 +453,15 @@ begin end; +procedure TLSMregForm.HideTabs; +var + i: Integer; +begin + for i := 1 to PageControl.PageCount-1 do // i=1 --> keep 1st page visible + PageControl.Pages[i].TabVisible := false; +end; + + procedure TLSMregForm.OutBtnClick(Sender: TObject); var i: integer; @@ -394,7 +498,7 @@ begin CorrsChkBox.Checked := true; MeansChkBox.Checked := true; VarChkBox.Checked := false; - SDChkBox.Checked := true; + StdDevChkBox.Checked := true; MatSaveChkBox.Checked := false; PredictChkBox.Checked := false; @@ -403,6 +507,7 @@ begin InProb.Text := FormatFloat('0.00', DEFAULT_ALPHA_LEVEL); SetLength(IndepVarsCols, NoVariables+1); + HideTabs; UpdateBtnStates; end; @@ -412,11 +517,21 @@ var lSelected: Boolean; begin inherited; - + + if Assigned(FRegressionFrame) then + FRegressionFrame.UpdateBtnStates; + if Assigned(FCrossProductsFrame) then + FCrossProductsFrame.UpdateBtnStates; + if Assigned(FCorrelationsFrame) then + FCorrelationsFrame.UpdateBtnStates; + if Assigned(FVarCovarFrame) then + FVarCovarFrame.UpdateBtnStates; + if Assigned(FMeanVarStddevFrame) then + FMeanVarStddevFrame.UpdateBtnStates; + lSelected := AnySelected(VarList); DepInBtn.Enabled := lSelected; InBtn.Enabled := lSelected; - OutBtn.Enabled := AnySelected(IndepVars); DepOutBtn.Enabled := DepVar.Text <> ''; AllBtn.Enabled := VarList.Items.Count > 0; diff --git a/applications/lazstats/source/units/matrixlib.pas b/applications/lazstats/source/units/matrixlib.pas index 595973336..6df5adfaf 100644 --- a/applications/lazstats/source/units/matrixlib.pas +++ b/applications/lazstats/source/units/matrixlib.pas @@ -8,6 +8,9 @@ uses Classes, SysUtils, Dialogs, Globals, DictionaryUnit, FunctionsLib, DataProcs, MainUnit; +//type +// TRegItem = (riMeanVarStdDev, riXTX); + procedure GridDotProd(col1, col2: integer; out Product: double; var Ngood: integer); procedure GridXProd(NoSelected : integer; @@ -27,7 +30,7 @@ procedure Correlations(NoSelected: integer; const Selected: IntDyneVec; procedure MatAxB(const A, B, C: DblDyneMat; BRows, BCols, CRows, CCols: Integer; out ErrorCode: boolean); -procedure MatTrn(var A, B: DblDyneMat; BRows, BCols: Integer); +procedure MatTrn(var A: DblDyneMat; const B: DblDyneMat; BRows, BCols: Integer); procedure nonsymroots(a : DblDyneMat; nv : integer; var nf : integer; c : real; @@ -46,6 +49,7 @@ procedure EffectCode(GridCol, min, max : integer; VAR startcol : integer; VAR endcol : integer; VAR novectors : integer); + procedure MReg(NoIndep: integer; const IndepCols: IntDyneVec; DepCol: integer; const RowLabels: StrDyneVec; const Means, Variances, StdDevs, BWeights, BetaWeights, BStdErrs, Bttests, tProbs: DblDyneVec; @@ -368,8 +372,8 @@ end; { of MATAxB } //------------------------------------------------------------------- -// transpose the b matrix and return it in a -procedure MatTrn(var A, B: DblDyneMat; BRows, BCols : integer); +// transpose the B matrix and return it in A +procedure MatTrn(var A: DblDyneMat; const B: DblDyneMat; BRows, BCols : integer); var i, j: integer; begin @@ -624,27 +628,27 @@ procedure MReg(NoIndep: integer; const IndepCols: IntDyneVec; DepCol: integer; PrintAll: boolean; AReport: TStrings); var i, j, N: integer; - X: DblDyneMat; - XT: DblDyneMat; - XTX: DblDyneMat; - XTY: DblDyneVec; - Y: DblDyneVec; - indx: IntDyneVec; - ColLabels: StrDyneVec; + X: DblDyneMat = nil; + XT: DblDyneMat = nil; + XTX: DblDyneMat = nil; + XTY: DblDyneVec = nil; + Y: DblDyneVec = nil; + indx: IntDyneVec = nil; + ColLabels: StrDyneVec = nil; F, Prob, VarY, SDY, MeanY: double; value, TOL, VIF, AdjR2: double; SSY, SSres, resvar, SSreg: double; title: string; deplabel: string; - errcode: boolean; + errcode: boolean = false; begin Assert(OS3MainFrm <> nil); - SetLength(X, NoCases+1, NoIndep+1); // augmented independent var. matrix - SetLength(XT, NoIndep+1, NoCases); // transpose of independent var's - SetLength(XTX, NoIndep+1, NoIndep+1); // product of transpose X times X - SetLength(Y, NCases+1); // Y variable values - SetLength(XTY, NoIndep+1); // X transpose times Y + SetLength(X, NoCases+1, NoIndep+1); // augmented independent var. matrix + SetLength(XT, NoIndep+1, NoCases); // transpose of independent var's + SetLength(XTX, NoIndep+1, NoIndep+1); // product of (transpose X) times X + SetLength(Y, NCases+1); // Y variable values + SetLength(XTY, NoIndep+1); // (X transpose) times Y SetLength(indx, NoIndep+1); SetLength(ColLabels, NCases); @@ -706,9 +710,11 @@ begin VarY := VarY / (NCases - 1); SDY := sqrt(VarY); - AReport.Add('Variance Y: %10.3f', [VarY]); - AReport.Add('SSY: %10.3f', [SSY]); - AReport.Add('SDY: %10.3f', [SDY]); + AReport.Add('Sum of Squares Y: %20.3f', [SSY]); + AReport.Add('Variance Y: %20.3f', [VarY]); + AReport.Add('Std. Deviation Y: %20.3f', [SDY]); + AReport.Add(''); + AReport.Add(DIVIDER_SMALL); // augment the matrix for i := 1 to NCases do @@ -719,8 +725,11 @@ begin MatTrn(XT, X, NCases, NoIndep+1); if PrintAll then begin + AReport.Add(''); title := 'XT MATRIX'; MatPrint(XT, NoIndep+1, NCases, title, RowLabels, ColLabels, NCases, AReport); + AReport.Add(DIVIDER_SMALL); + AReport.Add(''); end; // get product of the augmented X transpose times augmented X @@ -729,6 +738,8 @@ begin begin title := 'XTX MATRIX'; MatPrint(XTX, Noindep+1, NoIndep+1, title, RowLabels, RowLabels, NCases, AReport); + AReport.Add(DIVIDER_SMALL); + AReport.Add(''); end; //Get means, variances and standard deviations @@ -747,8 +758,14 @@ begin if PrintAll then begin DynVectorPrint(Means, NoIndep+1, 'MEANS', RowLabels, NCases, AReport); + AReport.Add(DIVIDER_SMALL); + AReport.Add(''); DynVectorPrint(Variances, NoIndep+1,'VARIANCES',RowLabels, NCases, AReport); - DynVectorPrint(StdDevs, NoIndep+1, 'STD. DEV.S', RowLabels, NCases, AReport); + AReport.Add(DIVIDER_SMALL); + AReport.Add(''); + DynVectorPrint(StdDevs, NoIndep+1, 'STD. DEVs', RowLabels, NCases, AReport); + AReport.Add(DIVIDER_SMALL); + AReport.Add(''); end; // get product of the augmented X transpose matrix times the Y vector @@ -756,14 +773,19 @@ begin for j := 0 to NCases-1 do XTY[i] := XTY[i] + (XT[i,j] * Y[j]); if PrintAll then + begin DynVectorPrint(XTY, NoIndep+1, 'XTY VECTOR', RowLabels, NCases, AReport); + AReport.Add(DIVIDER_SMALL); + end; // get inverse of the augmented cross products matrix among independent variables SVDInverse(XTX,N); if PrintAll then begin + AReport.Add(''); title := 'XTX MATRIX INVERSE'; MatPrint(XTX, NoIndep+1, NoIndep+1, title, RowLabels, RowLabels, NCases, AReport); + AReport.Add(DIVIDER); end; // multiply augmented inverse matrix times the XTY vector @@ -797,23 +819,24 @@ begin AdjR2 := 1.0 - (1.0 - R2) * (NCases - 1) / (NCases - N); if PrintAll then begin + AReport.Add(''); AReport.Add('Dependent variable: ' + deplabel); AReport.Add(''); DynVectorPrint(BWeights, NoIndep+1, 'B WEIGHTS', RowLabels, NCases, AReport); - AReport.Add(''); + AReport.Add(DIVIDER_SMALL); AReport.Add(''); AReport.Add('Dependent variable: ' + deplabel); AReport.Add(''); DynVectorPrint(BetaWeights, NoIndep, 'BETA WEIGHTS', RowLabels, NCases, AReport); - AReport.Add(''); + AReport.Add(DIVIDER_SMALL); AReport.Add(''); DynVectorPrint(BStdErrs, NoIndep+1, 'B STD.ERRORS', RowLabels, NCases, AReport); AReport.Add(''); DynVectorPrint(Bttests, NoIndep+1, 'B t-test VALUES', RowLabels, NCases, AReport); AReport.Add(''); DynVectorPrint(tprobs, NoIndep+1, 'B t VALUE PROBABILITIES', RowLabels, NCases, AReport); + AReport.Add(DIVIDER); AReport.Add(''); - AReport.Add('SSY: %10.2f', [SSY]); AReport.Add('SSreg: %10.2f', [SSreg]); AReport.Add('SSres: %10.2f', [SSres]); @@ -829,6 +852,8 @@ begin //AReport.Add('Standard Error of Estimate = %8.2f', [stderrest]); end; + AReport.Add(DIVIDER_SMALL); + AReport.Add(''); RowLabels[N-1] := 'Intercept'; AReport.Add(' Variable Beta B Std.Err. t prob VIF TOL'); AReport.Add('---------- ---------- ---------- ---------- ---------- ---------- --------- ----------');