LazStats: More refactoring of ResistanceLineUnit

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7757 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-10-10 11:28:34 +00:00
parent a91ba1bc04
commit 3cf0e45644

View File

@ -11,7 +11,7 @@ interface
uses uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls, Buttons, Printers, ComCtrls, StdCtrls, ExtCtrls, Buttons, Printers, ComCtrls, Grids,
MainUnit, Globals, DataProcs, DictionaryUnit, MainUnit, Globals, DataProcs, DictionaryUnit,
MathUnit, BasicStatsReportAndChartFormUnit; MathUnit, BasicStatsReportAndChartFormUnit;
@ -57,10 +57,14 @@ type
procedure PlotXY(const XPoints, YPoints: DblDyneVec; procedure PlotXY(const XPoints, YPoints: DblDyneVec;
ARegressionResults: TBivariateRegressionResults); ARegressionResults: TBivariateRegressionResults);
function PrepareData(ADataGrid: TStringGrid;
out xCol, ycol: Integer; out XData, YData: DblDyneVec;
out ColNoSelected: IntDyneVec): Boolean;
procedure ResidualsToGrid(xCol, yCol: Integer; procedure ResidualsToGrid(xCol, yCol: Integer;
const AColNoSelected: IntDyneVec; Slope, Intercept: Double); const AColNoSelected: IntDyneVec; Slope, Intercept: Double);
procedure ResistantLineAnalysis(const xyPoints: DblDyneMat; procedure ResistantLineAnalysis(const XData, YData: DblDyneVec;
out XMedians, yMedians: DblDyneVec; out GrpSize: IntDyneVec); out XMedians, yMedians: DblDyneVec; out GrpSize: IntDyneVec);
procedure WriteMedianReport(AReport: TStrings; procedure WriteMedianReport(AReport: TStrings;
@ -87,7 +91,7 @@ implementation
{$R *.lfm} {$R *.lfm}
uses uses
Math, Grids, Math,
TATypes, TAChartUtils, TAChartAxisUtils, TALegend, TASources, TACustomSeries, TATypes, TAChartUtils, TAChartAxisUtils, TALegend, TASources, TACustomSeries,
ChartFrameUnit, Utils, GridProcs; ChartFrameUnit, Utils, GridProcs;
@ -136,14 +140,14 @@ end;
procedure TResistanceLineForm.Compute; procedure TResistanceLineForm.Compute;
var var
xyPoints: DblDyneMat = nil; // 1st index: x or y, 2nd index: data index xValues: DblDyneVec = nil;
yValues: DblDyneVec = nil;
xMedians: DblDyneVec = nil; xMedians: DblDyneVec = nil;
yMedians: DblDyneVec = nil; yMedians: DblDyneVec = nil;
colNoSelected : IntDyneVec = nil; colNoSelected : IntDyneVec = nil;
grpSize: IntDyneVec = nil; grpSize: IntDyneVec = nil;
xCol, yCol: Integer; xCol, yCol: Integer;
regressionRes: TBivariateRegressionResults; regressionRes: TBivariateRegressionResults;
N: Integer;
confBand: Double; confBand: Double;
slope1, slope2, slopeRL: Double; slope1, slope2, slopeRL: Double;
c1, c2, c3, c: Double; c1, c2, c3, c: Double;
@ -152,48 +156,19 @@ var
begin begin
dataGrid := OS3MainFrm.DataGrid; dataGrid := OS3MainFrm.DataGrid;
xCol := GetVariableIndex(dataGrid, XEdit.Text);
yCol := GetVariableIndex(dataGrid, YEdit.Text);
if xCol = -1 then
begin
ErrorMsg('X variable not specified or not found.');
exit;
end;
if yCol = -1 then
begin
ErrorMsg('Y variable not specified or not found.');
exit;
end;
SetLength(colNoSelected, 2);
colNoSelected[0] := xCol;
colNoSelected[1] := yCol;
// Get values from the grid // Get values from the grid
SetLength(xyPoints, 2); if not PrepareData(dataGrid, xCol, yCol, xValues, yvalues, colNoSelected) then
xyPoints[0] := CollectValues(dataGrid, xCol, colNoSelected);
xyPoints[1] := CollectValues(dataGrid, ycol, colNoSelected);
N := Length(xyPoints[0]);
if N < 3 then
begin
ErrorMsg('At least three data points required.');
exit; exit;
end;
if N <> Length(xyPoints[1]) then
begin
ErrorMsg('Equal count of cases required for x and y variables.');
exit;
end;
// Sort on the x values // Sort on the x values
SortOnX(xyPoints[0], xyPoints[1]); SortOnX(xValues, yValues);
// Calculate bivariate regression // Calculate bivariate regression
confBand := StrToFloat(ConfEdit.Text) / 100; confBand := StrToFloat(ConfEdit.Text) / 100;
Calc_BivariateRegression(xyPoints[0], xyPoints[1], confBand, regressionRes); Calc_BivariateRegression(xValues, yValues, confBand, regressionRes);
// Do the resistant line analysis // Do the resistant line analysis
ResistantLineAnalysis(xyPoints, xMedians, yMedians, grpSize); ResistantLineAnalysis(xValues, yValues, xMedians, yMedians, grpSize);
slope1 := (yMedians[1] - yMedians[0]) / (xMedians[1] - xMedians[0]); slope1 := (yMedians[1] - yMedians[0]) / (xMedians[1] - xMedians[0]);
slope2 := (yMedians[2] - yMedians[1]) / (xMedians[2] - xMedians[1]); slope2 := (yMedians[2] - yMedians[1]) / (xMedians[2] - xMedians[1]);
@ -230,10 +205,10 @@ begin
// Plot results in ChartFrame // Plot results in ChartFrame
if PlotPointsChk.Checked then if PlotPointsChk.Checked then
PlotXY(xyPoints[0], xyPoints[1], regressionRes); PlotXY(xValues, yValues, regressionRes);
if PlotMediansChk.Checked then if PlotMediansChk.Checked then
PlotMedians(XMedians, YMedians, slopeRL, c); PlotMedians(xMedians, yMedians, slopeRL, c);
end; end;
@ -356,6 +331,54 @@ begin
end; end;
function TResistanceLineForm.PrepareData(ADataGrid: TStringGrid;
out xCol, ycol: Integer; out XData, YData: DblDyneVec;
out ColNoSelected: IntDyneVec): Boolean;
var
N: Integer;
begin
Result := false;
ColNoSelected := nil;
XData := nil;
YData := nil;
xCol := GetVariableIndex(ADataGrid, XEdit.Text);
yCol := GetVariableIndex(ADataGrid, YEdit.Text);
if xCol = -1 then
begin
ErrorMsg('X variable not specified or not found.');
exit;
end;
if yCol = -1 then
begin
ErrorMsg('Y variable not specified or not found.');
exit;
end;
SetLength(ColNoSelected, 2);
ColNoSelected[0] := xCol;
ColNoSelected[1] := yCol;
XData := CollectValues(ADataGrid, xCol, colNoSelected);
YData := CollectValues(ADataGrid, ycol, colNoSelected);
N := Length(XData);
if N < 3 then
begin
ErrorMsg('At least three data points required.');
exit;
end;
if N <> Length(YData) then
begin
ErrorMsg('Equal count of cases required for x and y variables.');
exit;
end;
Result := true;
end;
procedure TResistanceLineForm.Reset; procedure TResistanceLineForm.Reset;
var var
i: integer; i: integer;
@ -421,14 +444,14 @@ begin
end; end;
{ Do the resistant line analysis } { Do the resistant line analysis }
procedure TResistanceLineForm.ResistantLineAnalysis(const xyPoints: DblDyneMat; procedure TResistanceLineForm.ResistantLineAnalysis(const XData, YData: DblDyneVec;
out XMedians, yMedians: DblDyneVec; out GrpSize: IntDyneVec); out XMedians, yMedians: DblDyneVec; out GrpSize: IntDyneVec);
var var
i, N, offs: Integer; i, N, offs: Integer;
xVector: DblDyneVec = nil; xVector: DblDyneVec = nil;
yVector: DblDyneVec = nil; yVector: DblDyneVec = nil;
begin begin
N := Length(xyPoints[0]); N := Length(XData);
GrpSize := nil; GrpSize := nil;
XMedians := nil; XMedians := nil;
@ -453,8 +476,8 @@ begin
offs := 0; offs := 0;
for i := 0 to GrpSize[1] - 1 do for i := 0 to GrpSize[1] - 1 do
begin begin
xVector[i] := xyPoints[0, i + offs]; xVector[i] := XData[i + offs];
yVector[i] := xyPoints[1, i + offs]; yVector[i] := YData[i + offs];
end; end;
xMedians[0] := Calc_Median(xVector); xMedians[0] := Calc_Median(xVector);
yMedians[0] := Calc_Median(yVector); yMedians[0] := Calc_Median(yVector);
@ -465,8 +488,8 @@ begin
offs := GrpSize[0]; offs := GrpSize[0];
for i := 0 to GrpSize[1] - 1 do for i := 0 to GrpSize[1] - 1 do
begin begin
xVector[i] := xyPoints[0, i + offs]; xVector[i] := XData[i + offs];
yVector[i] := xyPoints[1, i + offs]; yVector[i] := YData[i + offs];
end; end;
xMedians[1] := Calc_Median(xVector); xMedians[1] := Calc_Median(xVector);
yMedians[1] := Calc_Median(yVector); yMedians[1] := Calc_Median(yVector);
@ -477,8 +500,8 @@ begin
offs := GrpSize[0] + GrpSize[1]; offs := GrpSize[0] + GrpSize[1];
for i := 0 to GrpSize[2] - 1 do for i := 0 to GrpSize[2] - 1 do
begin begin
xVector[i] := xyPoints[0, i + offs]; xVector[i] := XData[i + offs];
yVector[i] := xyPoints[1, i + offs]; yVector[i] := YData[i + offs];
end; end;
xMedians[2] := Calc_Median(xVector); xMedians[2] := Calc_Median(xVector);
yMedians[2] := Calc_Median(yVector); yMedians[2] := Calc_Median(yVector);