From fb92b9fb1da0b54f60f3546a02800dfc48bf70bc Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Mon, 12 Oct 2020 13:43:51 +0000 Subject: [PATCH] LazStats: Integrate charts of WLSUnit into tabs on the WLSFrm git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7772 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../forms/analysis/descriptive/plotxyunit.pas | 10 +- .../analysis/multiple_regression/wlsunit.lfm | 20 +- .../analysis/multiple_regression/wlsunit.pas | 343 ++++++++++++------ .../lazstats/source/forms/mainunit.pas | 2 +- .../lazstats/source/units/matrixlib.pas | 24 +- 5 files changed, 281 insertions(+), 118 deletions(-) diff --git a/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.pas b/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.pas index 68268a53b..52a1787dc 100644 --- a/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.pas +++ b/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.pas @@ -161,6 +161,7 @@ var tmpX: DblDyneVec = nil; tmpY: DblDyneVec = nil; conf: DblDyneVec = nil; + ext: TDoubleRect; xmin, xmax, ymin, ymax: Double; rightLabels: TListChartSource; topLabels: TListChartSource; @@ -204,11 +205,11 @@ begin ser := FChartFrame.PlotXY(ptLines, XPoints, conf, nil, nil, 'Lower confidence band', clRed); rightLabels.Add(ser.yValue[ser.Count-1], ser.YValue[ser.Count-1], 'LCL'); end; - + { FChartFrame.Chart.Prepare; FChartFrame.GetXRange(xmin, xmax, false); FChartFrame.GetYRange(ymin, ymax, false); - + } // Draw means if MeansChk.Checked then with ARegressionResults do @@ -222,10 +223,11 @@ begin // Draw regression line if LineChk.Checked then begin + ext := FChartFrame.Chart.GetFullExtent; SetLength(tmpX, 2); SetLength(tmpY, 2); - tmpX[0] := xmin; - tmpX[1] := xmax; + tmpX[0] := ext.a.x; + tmpX[1] := ext.b.x; with ARegressionResults do begin tmpY[1] := tmpX[1] * Slope + Intercept; diff --git a/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.lfm b/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.lfm index ea9adf9c3..396b78718 100644 --- a/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.lfm +++ b/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.lfm @@ -390,19 +390,35 @@ inherited WLSFrm: TWLSFrm Height = 412 Top = 8 Width = 500 - ActivePage = OLSPage + ActivePage = ResidualsRegPage Align = alClient BorderSpacing.Left = 4 BorderSpacing.Top = 8 BorderSpacing.Right = 8 BorderSpacing.Bottom = 8 - TabIndex = 0 + TabIndex = 1 TabOrder = 2 object OLSPage: TTabSheet Caption = 'OLS Regression' end object ResidualsRegPage: TTabSheet Caption = 'Squared Residuals Regression' + ClientHeight = 384 + ClientWidth = 492 + object ResRegPageControl: TPageControl + Left = 8 + Height = 368 + Top = 8 + Width = 476 + ActivePage = ResRegReportPage + Align = alClient + BorderSpacing.Around = 8 + TabIndex = 0 + TabOrder = 0 + object ResRegReportPage: TTabSheet + Caption = 'Report' + end + end end object WLSPage: TTabSheet Caption = 'WLS Regression' diff --git a/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.pas b/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.pas index b3b0405e2..fb37cef61 100644 --- a/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.pas +++ b/applications/lazstats/source/forms/analysis/multiple_regression/wlsunit.pas @@ -8,7 +8,7 @@ uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Buttons, ExtCtrls, ComCtrls, Globals, MainUnit, DictionaryUnit, Matrixlib, - DataProcs, BlankFrmUnit, ReportFrameUnit, BasicStatsParamsFormUnit; //BasicStatsReportAndChartFormUnit; + DataProcs, BlankFrmUnit, ReportFrameUnit, ChartFrameUnit, BasicStatsParamsFormUnit; //BasicStatsReportAndChartFormUnit; type @@ -21,7 +21,9 @@ type IndOutBtn: TBitBtn; PageControl: TPageControl; OLSPage: TTabSheet; + ResRegPageControl: TPageControl; ResidualsRegPage: TTabSheet; + ResRegReportPage: TTabSheet; WLSPage: TTabSheet; WghtInBtn: TBitBtn; WghtOutBtn: TBitBtn; @@ -56,10 +58,19 @@ type OLSReportFrame: TReportFrame; ResidualsRegReportFrame: TReportFrame; WLSReportFrame: TReportFrame; + + procedure CreateOrGetChartFrame(AColIndex: Integer; AVarName: String; + out AMemo: TMemo; out AChartFrame: TChartFrame); + + function GetPageCaption(AVarName: String): String; + procedure PredictIt(ColNoSelected: IntDyneVec; NoVars: integer; Means, StdDevs, BetaWeights: DblDyneVec; StdErrEst: double; NoIndepVars: integer); + procedure PlotXY(AChartFrame: TChartFrame; const XPoints, YPoints, UpConf, LowConf: DblDyneVec; + ConfBand, XMean, YMean, R, Slope, Intercept: Double; XLabel, YLabel: String); + procedure PlotXY(Xpoints, Ypoints, UpConf, LowConf: DblDyneVec; ConfBand, Xmean, Ymean, R, Slope, Intercept: double; Xmax, Xmin, Ymax, Ymin: double; @@ -86,6 +97,7 @@ implementation {$R *.lfm} uses + TAChartUtils, TALegend, Utils, GridProcs, MathUnit; { TWLSFrm } @@ -108,7 +120,7 @@ begin ResidualsRegReportFrame := TReportFrame.Create(self); ResidualsRegReportFrame.Name := ''; - ResidualsRegReportFrame.Parent := ResidualsRegPage; + ResidualsRegReportFrame.Parent := ResRegReportPage; ResidualsRegReportFrame.Align := alClient; ResidualsRegReportFrame.BorderSpacing.Left := 0; ResidualsRegReportFrame.BorderSpacing.Top := 0; @@ -167,6 +179,8 @@ var errorcode: Boolean = false; C: TWinControl; msg: String; + chartFrame: TChartFrame; + memo: TMemo; begin if not Validate(msg, C) then begin @@ -187,10 +201,10 @@ begin SetLength(tprobs, NoVariables + 2); SetLength(RowLabels, NoVariables + 2); SetLength(IndepCols, NoVariables + 2); - SetLength(Xpoints, NoCases + 1); - SetLength(Ypoints, NoCases + 1); - SetLength(UpConf, NoCases + 1); - SetLength(lowConf, NoCases + 1); +// SetLength(Xpoints, NoCases + 1); +// SetLength(Ypoints, NoCases + 1); +// SetLength(UpConf, NoCases + 1); +// SetLength(lowConf, NoCases + 1); SetLength(ColNoSelected, 2); lReport := TStringList.Create; @@ -198,7 +212,7 @@ begin NCases := NoCases; NoIndep := IndVarList.Items.Count; - // wp: Next SetLength crashes... + // wp: This SetLength crashes... // SetLength(IndepCols, NoIndep+1); // +1 because the dep col will be stuffed in there, too // SetLength(RowLabels, NoIndep); @@ -334,7 +348,7 @@ 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 + for j := 0 to NoIndep - 1 do begin pos := IndepCols[j]; X := StrToFloat(OS3MainFrm.DataGrid.Cells[pos,i]); @@ -342,22 +356,24 @@ begin end; predicted := predicted + BWeights[Noindep]; predicted := abs(predicted); - OS3MainFrm.DataGrid.Cells[col-1,i] := Format('%8.3f', [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('%8.3f', [predicted]); + OS3MainFrm.DataGrid.Cells[col,i] := Format('%.3f', [predicted]); end; // if valid case end; // next i end; // if regresChk // Now, plot squared residuals against each independent variable - if PlotChk.Checked and RegResChk.Checked then + if RegResChk.Checked then begin xCol := DepCol; for ii := 0 to NoIndep - 1 do begin + SetLength(xPoints, NoCases); + SetLength(yPoints, NoCases); yCol := IndepCols[ii]; N := 0; ColNoSelected[0] := xCol; @@ -377,7 +393,6 @@ begin for i := 1 to NoCases do begin if (not DataProcs.GoodRecord(i,NoSelected,ColNoSelected)) then continue; - N := N + 1; X := StrToFloat(OS3MainFrm.DataGrid.Cells[Xcol,i]); Y := StrToFloat(OS3MainFrm.DataGrid.Cells[Ycol,i]); Xpoints[N] := X; @@ -391,7 +406,10 @@ begin Xvariance := Xvariance + X * X; Yvariance := Yvariance + Y * Y; R := R + X * Y; + N := N + 1; end; + SetLength(xPoints, N); + SetLength(yPoints, N); // sort on X SortOnX(xPoints, yPoints); @@ -418,8 +436,7 @@ begin Intercept := Ymean - Slope * Xmean; // Now, print the descriptive statistics if requested - lReport.Add('X versus Y Plot'); - lReport.Add(''); + lReport.Clear; lReport.Add('Data file: %s', [OS3MainFrm.FileNameEdit.Text]); lReport.Add(''); lReport.Add('Variables:'); @@ -437,17 +454,13 @@ begin lReport.Add('Standard Error of Estimate: %8.2f', [SEPred]); lReport.Add('Number of good cases: %8d', [N]); -// FReportFrame.DisplayReport(lReport); -// lReport.Clear; - lReport.Add(''); - lReport.Add(DIVIDER); - lReport.Add(''); - - // get upper and lower confidence points for each X value + // Get upper and lower confidence points for each X value + SetLength(UpConf, N); + SetLength(LowConf, N); ConfBand := 0.95; DF := N - 2; t := inverset(ConfBand,DF); - for i := 1 to N do + for i := 0 to N-1 do begin X := Xpoints[i]; predicted := Slope * X + Intercept; @@ -458,10 +471,26 @@ begin if (lowConf[i] < Ymin) then Ymin := lowConf[i]; end; - // plot the values (and optional line and confidence band if elected) - PlotXY(Xpoints, Ypoints, UpConf, lowConf, ConfBand, Xmean, Ymean, R, - Slope, Intercept, Xmax, Xmin, Ymax, Ymin, N, XLabel, YLabel); - BlankFrm.ShowModal; + // Plot the values, line and confidence band + CreateOrGetChartFrame(yCol, yLabel, memo, chartFrame); + chartFrame.Clear; + PlotXY(chartFrame, XPoints, YPoints, upConf, lowConf, confBand, xMean, yMean, R, slope, intercept, xLabel, yLabel); + memo.Lines.Assign(lReport); + lReport.Clear; + { + if NormPltChk.Checked then + PlotNormalDist(chartFrame, normDistValue); + PlotFreq(chartFrame, col, cellVal, xLabels, freq); + } + + + + if PlotChk.Checked then + begin + PlotXY(Xpoints, Ypoints, UpConf, lowConf, ConfBand, Xmean, Ymean, R, + Slope, Intercept, Xmax, Xmin, Ymax, Ymin, N, XLabel, YLabel); + BlankFrm.ShowModal; + end; end; // FReportFrame.DisplayReport(lReport); @@ -586,6 +615,59 @@ begin end; +procedure TWLSFrm.CreateOrGetChartFrame(AColIndex: Integer; AVarName: String; + out AMemo: TMemo; out AChartFrame: TChartFrame); +var + sheetTitle: String; + tabSheet: TTabSheet; + i: Integer; +begin + sheetTitle := GetPageCaption(AVarName); + + // Find existing sheet first. + for i := 1 to ResRegPageControl.PageCount-1 do + if ResRegPageControl.Pages[i].Caption = sheetTitle then begin + tabSheet := ResRegPageControl.Pages[i]; + AChartFrame := tabSheet.Controls[0] as TChartFrame; + AMemo := tabSheet.Controls[1] as TMemo; + exit; + end; + + // Not found: create new sheet ... + tabSheet := ResRegPageControl.AddTabSheet; + tabSheet.Caption := sheetTitle; + tabSheet.Tag := AColIndex; + + // ... and add ChartFrame + AChartFrame := TChartFrame.Create(tabSheet); + AChartFrame.Parent := tabSheet; + AChartFrame.Align := alClient; + AChartFrame.Chart.Legend.Alignment := laBottomCenter; + AChartFrame.Chart.Legend.ColumnCount := 3; + AChartFrame.Chart.Legend.TextFormat := tfHTML; + AChartFrame.Chart.BottomAxis.Intervals.MaxLength := 80; + AChartFrame.Chart.BottomAxis.Intervals.MinLength := 30; + + // ... and add memo + AMemo := TMemo.Create(tabSheet); + AMemo.Parent := tabSheet; + AMemo.Align := alBottom; + AMemo.BorderStyle := bsNone; + AMemo.Font.Name := 'Courier New'; + AMemo.Font.Size := 8; + AMemo.ReadOnly := true; + AMemo.Scrollbars := ssAutoBoth; + AMemo.WordWrap := false; + + // ... and splitter + with TSplitter.Create(tabSheet) do + begin + Parent := tabSheet; + Align := alBottom; + end; +end; + + procedure TWLSFrm.DepInBtnClick(Sender: TObject); var index: integer; @@ -611,6 +693,12 @@ begin end; +function TWLSFrm.GetPageCaption(AVarName: String): String; +begin + Result := 'Plot of ' + AVarName; +end; + + procedure TWLSFrm.IndInBtnClick(Sender: TObject); var i: integer; @@ -661,93 +749,134 @@ begin end; end; -// routine obtains predicted raw and standardized scores and their -// residuals. It is assumed that the dependent variable is last in the -// list of variable column pointers stored in the ColNoSelected vector. -// Get the z predicted score and its residual +{ Routine obtains predicted raw and standardized scores and their + residuals. It is assumed that the dependent variable is last in the + list of variable column pointers stored in the ColNoSelected vector. + Get the z predicted score and its residual } procedure TWLSFrm.PredictIt(ColNoSelected: IntDyneVec; NoVars: integer; - Means, StdDevs, BetaWeights: DblDyneVec; - StdErrEst: double; NoIndepVars: integer); + Means, StdDevs, BetaWeights: DblDyneVec; StdErrEst: double; NoIndepVars: integer); var - col, i, j, k, Index: integer; - predicted, zpredicted, z1, z2, resid, residsqr : double; + col, i, j, k, Index: integer; + predicted, zpredicted, z1, z2, resid, residsqr: double; begin - col := NoVariables + 1; + col := NoVariables + 1; // NoVariables := col; - OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables); - DictionaryFrm.DictGrid.ColCount := 8; - DictionaryFrm.NewVar(col); - OS3MainFrm.DataGrid.Cells[col,0] := 'Pred.z'; - DictionaryFrm.DictGrid.Cells[1,col] := 'Pred.z'; + OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables); + DictionaryFrm.DictGrid.ColCount := 8; + DictionaryFrm.NewVar(col); + OS3MainFrm.DataGrid.Cells[col,0] := 'Pred.z'; + DictionaryFrm.DictGrid.Cells[1,col] := 'Pred.z'; - col := NoVariables + 1; + col := NoVariables + 1; // NoVariables := col; - DictionaryFrm.NewVar(col); - OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables); - OS3MainFrm.DataGrid.Cells[col,0] := 'z Resid.'; - DictionaryFrm.DictGrid.Cells[1,col] := 'z Resid.'; - OS3MainFrm.DataGrid.ColCount := OS3MainFrm.DataGrid.ColCount + 2; - for i := 1 to NoCases do - begin - zpredicted := 0.0; - for j := 0 to NoIndepVars - 1 do - begin - k := ColNoSelected[j]; - z1 := (StrToFloat(OS3MainFrm.DataGrid.Cells[k,i]) - Means[j]) / StdDevs[j]; - zpredicted := zpredicted + (z1 * BetaWeights[j]); - end; - OS3MainFrm.DataGrid.Cells[col-1,i] := Format('%8.4f',[zpredicted]); + DictionaryFrm.NewVar(col); + OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables); + OS3MainFrm.DataGrid.Cells[col,0] := 'z Resid.'; + DictionaryFrm.DictGrid.Cells[1,col] := 'z Resid.'; + OS3MainFrm.DataGrid.ColCount := OS3MainFrm.DataGrid.ColCount + 2; + for i := 1 to NoCases do + begin + zpredicted := 0.0; + for j := 0 to NoIndepVars - 1 do + begin + k := ColNoSelected[j]; + z1 := (StrToFloat(OS3MainFrm.DataGrid.Cells[k,i]) - Means[j]) / StdDevs[j]; + zpredicted := zpredicted + (z1 * BetaWeights[j]); + end; + OS3MainFrm.DataGrid.Cells[col-1,i] := Format('%.4f',[zpredicted]); - if StdDevs[NoVars-1] <> 0.0 then - begin - Index := ColNoSelected[NoVars-1]; - z2 := StrToFloat(OS3MainFrm.DataGrid.Cells[Index,i]); - z2 := (z2 - Means[NoVars-1]) / StdDevs[NoVars-1]; // z score - OS3MainFrm.DataGrid.Cells[col,i] := Format('%8.4f',[z2 - zpredicted]); // z residual - end; - end; + if StdDevs[NoVars-1] <> 0.0 then + begin + Index := ColNoSelected[NoVars-1]; + z2 := StrToFloat(OS3MainFrm.DataGrid.Cells[Index,i]); + z2 := (z2 - Means[NoVars-1]) / StdDevs[NoVars-1]; // z score + OS3MainFrm.DataGrid.Cells[col,i] := Format('%.4f',[z2 - zpredicted]); // z residual + end; + end; - // Get raw predicted and residuals - col := NoVariables + 1; - OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables); - DictionaryFrm.NewVar(col); - DictionaryFrm.DictGrid.Cells[1,col] := 'Pred.Raw'; - OS3MainFrm.DataGrid.Cells[col,0] := 'Pred.Raw'; - // calculate raw predicted scores and store in DataGrid at col - for i := 1 to NoCases do - begin // predicted raw obtained from previously predicted z score - predicted := StrToFloat(OS3MainFrm.DataGrid.Cells[col-2,i]) * StdDevs[NoVars-1] + Means[NoVars-1]; - OS3MainFrm.DataGrid.Cells[col,i] := Format('%8.3f',[predicted]); - end; + // Get raw predicted and residuals + col := NoVariables + 1; + OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables); + DictionaryFrm.NewVar(col); + DictionaryFrm.DictGrid.Cells[1,col] := 'Pred.Raw'; + OS3MainFrm.DataGrid.Cells[col,0] := 'Pred.Raw'; - // Calculate residuals of predicted raw scores end; - col := NoVariables +1; - OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables); - DictionaryFrm.NewVar(col); - DictionaryFrm.DictGrid.Cells[1,col] := 'Raw Resid.'; - OS3MainFrm.DataGrid.Cells[col,0] := 'Raw Resid.'; + // calculate raw predicted scores and store in DataGrid at col + for i := 1 to NoCases do + begin // predicted raw obtained from previously predicted z score + predicted := StrToFloat(OS3MainFrm.DataGrid.Cells[col-2,i]) * StdDevs[NoVars-1] + Means[NoVars-1]; + OS3MainFrm.DataGrid.Cells[col,i] := Format('%.3f',[predicted]); + end; - for i := 1 to NoCases do - begin - Index := ColNoSelected[NoVars-1]; - resid := StrToFloat(OS3MainFrm.DataGrid.Cells[col-1,i]) - StrToFloat(OS3MainFrm.DataGrid.Cells[Index,i]); - OS3MainFrm.DataGrid.Cells[col,i] := Format('%8.3f',[resid]); - end; + // Calculate residuals of predicted raw scores end; + col := NoVariables +1; + OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables); + DictionaryFrm.NewVar(col); + DictionaryFrm.DictGrid.Cells[1,col] := 'Raw Resid.'; + OS3MainFrm.DataGrid.Cells[col,0] := 'Raw Resid.'; - // get square of raw residuals - col := NoVariables + 1; - DictionaryFrm.NewVar(col); - OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables); - DictionaryFrm.DictGrid.Cells[1,col] := 'ResidSqr'; - OS3MainFrm.DataGrid.Cells[col,0] := 'ResidSqr'; - for i := 1 to NoCases do - begin - residsqr := StrToFloat(OS3MainFrm.DataGrid.Cells[col-1,i]); - residsqr := residsqr * residsqr; - OS3MainFrm.DataGrid.Cells[col,i] := Format('%8.3f',[residsqr]); - end; + for i := 1 to NoCases do + begin + Index := ColNoSelected[NoVars-1]; + resid := StrToFloat(OS3MainFrm.DataGrid.Cells[col-1,i]) - StrToFloat(OS3MainFrm.DataGrid.Cells[Index,i]); + OS3MainFrm.DataGrid.Cells[col,i] := Format('%.3f',[resid]); + end; + + // get square of raw residuals + col := NoVariables + 1; + DictionaryFrm.NewVar(col); + OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables); + DictionaryFrm.DictGrid.Cells[1,col] := 'ResidSqr'; + OS3MainFrm.DataGrid.Cells[col,0] := 'ResidSqr'; + for i := 1 to NoCases do + begin + residsqr := StrToFloat(OS3MainFrm.DataGrid.Cells[col-1,i]); + residsqr := residsqr * residsqr; + OS3MainFrm.DataGrid.Cells[col,i] := Format('%8.3f',[residsqr]); + end; end; + +procedure TWLSFrm.PlotXY(AChartFrame: TChartFrame; + const XPoints, YPoints, UpConf, LowConf: DblDyneVec; + ConfBand, XMean, YMean, R, Slope, Intercept: Double; XLabel, YLabel: String); +var + xpts: DblDyneVec = nil; + ypts: DblDyneVec = nil; + ext: TDoubleRect; +begin + AChartFrame.SetFooter(Format('R(X,Y) = %.3f, Slope = %.3f, Intercept = %.3f', [ + R, Slope, Intercept + ])); + + // Data points + AChartFrame.SetXTitle(XLabel); + AChartFrame.SetYTitle(YLabel); + AChartFrame.PlotXY(ptSymbols, XPoints, YPoints, nil, nil, 'Data', DATA_COLORS[0]); + + // Regression line + SetLength(xpts, 2); + SetLengtH(ypts, 2); + ext := AChartFrame.Chart.GetFullExtent; + xpts[0] := ext.a.x; + xpts[0] := ext.b.x; + ypts[0] := Intercept + Slope * xpts[0]; + ypts[1] := Intercept + Slope * xpts[1]; + AChartFrame.PlotXY(ptLines, xpts, ypts, nil, nil, 'Predicted', clBlack); + + // Upper and lower confidence limit curves + AChartFrame.PlotXY(ptLines, XPoints, UpConf, nil, nil, 'UCL', clRed); + AChartFrame.PlotXY(ptLines, XPoints, LowConf, nil, nil, 'LCL', clRed); + + // Mean lines + AChartFrame.VertLine(XMean, clGreen, psDashDot, 'Mean ' + XLabel); +// topLabels.Add(XMean, XMean, 'Mean ' + XLabel); + + AChartFrame.HorLine(YMean, clGreen, psDash, 'Mean ' + YLabel); +// rightLabels.Add(YMean, YMean, 'Mean ' + YLabel); +end; + + procedure TWLSFrm.PlotXY(Xpoints, Ypoints, UpConf, LowConf : DblDyneVec; ConfBand, Xmean, Ymean, R, Slope, Intercept : double; Xmax, Xmin, Ymax, Ymin : double; @@ -887,7 +1016,7 @@ begin end; // draw points for x and y pairs - for i := 1 to N do + for i := 0 to N-1 do begin ypos := round(vhi * ( (Ymax - Ypoints[i]) / (Ymax - Ymin))); ypos := ypos + vtop; @@ -903,12 +1032,12 @@ begin if not (ConfBand = 0.0) then begin BlankFrm.Image1.Canvas.Pen.Color := clRed; - ypos := round(vhi * ((Ymax - UpConf[1]) / (Ymax - Ymin))); + ypos := round(vhi * ((Ymax - UpConf[0]) / (Ymax - Ymin))); ypos := ypos + vtop; - xpos := round(hwide * ( (Xpoints[1] - Xmin) / (Xmax - Xmin))); + xpos := round(hwide * ( (Xpoints[0] - Xmin) / (Xmax - Xmin))); xpos := xpos + hleft; BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); - for i := 2 to N do + for i := 1 to N-1 do begin ypos := round(vhi * ((Ymax - UpConf[i]) / (Ymax - Ymin))); ypos := ypos + vtop; @@ -916,12 +1045,12 @@ begin xpos := xpos + hleft; BlankFrm.Image1.Canvas.LineTo(xpos,ypos); end; - ypos := round(vhi * ((Ymax - LowConf[1]) / (Ymax - Ymin))); + ypos := round(vhi * ((Ymax - LowConf[0]) / (Ymax - Ymin))); ypos := ypos + vtop; - xpos := round(hwide * ( (Xpoints[1] - Xmin) / (Xmax - Xmin))); + xpos := round(hwide * ( (Xpoints[0] - Xmin) / (Xmax - Xmin))); xpos := xpos + hleft; BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); - for i := 2 to N do + for i := 1 to N-1 do begin ypos := round(vhi * ((Ymax - LowConf[i]) / (Ymax - Ymin))); ypos := ypos + vtop; diff --git a/applications/lazstats/source/forms/mainunit.pas b/applications/lazstats/source/forms/mainunit.pas index 277b105c4..738232217 100644 --- a/applications/lazstats/source/forms/mainunit.pas +++ b/applications/lazstats/source/forms/mainunit.pas @@ -2114,7 +2114,7 @@ procedure TOS3MainFrm.mnuAnalysisMultReg_WeightedClick(Sender: TObject); begin if WLSFrm = nil then Application.CreateForm(TWLSFrm, WLSFrm); - WLSFrm.ShowModal; + WLSFrm.Show; end; diff --git a/applications/lazstats/source/units/matrixlib.pas b/applications/lazstats/source/units/matrixlib.pas index c5f575551..6e38ff750 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; NCases: integer; out ErrorCode: boolean; + out R2, StdErrEst: double; out NCases: integer; out ErrorCode: boolean; PrintAll: boolean; AReport: TStrings); procedure Dynnonsymroots(var a : DblDyneMat; nv : integer; @@ -622,10 +622,26 @@ begin coef := nil; end; +{ Calculates a multiple regression on data in the mainform's grid + + NoIndep ..... Count of independent variables + IndepCols ... Grid column indices of the independent variables + DepCol ...... Grid column index of the dependent variable + RowLabels ... Names of the independent variables (they will be displayed in the + printout of matrices as rowlabels. + Means ....... Mean value for each independent variable + Variances ... Variance of each independent variable + StdDevs ..... Standard deviations of each independent variable + + NCases ...... Count of valid cases found 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. +} 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; NCases: integer; out ErrorCode: boolean; + out R2, StdErrEst: double; out NCases: integer; out ErrorCode: boolean; PrintAll: boolean; AReport: TStrings); var i, j, N: integer; @@ -718,8 +734,8 @@ begin AReport.Add(DIVIDER_SMALL); // augment the matrix - for i := 1 to NCases do - X[i-1, NoIndep] := 1.0; + for i := 0 to NCases-1 do + X[i, NoIndep] := 1.0; Y[NCases] := 1.0; // get transpose of augmented X matrix