2020-03-30 18:01:44 +00:00
|
|
|
unit WLSUnit;
|
|
|
|
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
2020-10-11 22:31:17 +00:00
|
|
|
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
|
|
|
|
StdCtrls, Buttons, ExtCtrls, ComCtrls,
|
|
|
|
Globals, MainUnit, DictionaryUnit, Matrixlib,
|
2020-10-12 13:43:51 +00:00
|
|
|
DataProcs, BlankFrmUnit, ReportFrameUnit, ChartFrameUnit, BasicStatsParamsFormUnit; //BasicStatsReportAndChartFormUnit;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
|
|
|
|
{ TWLSFrm }
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
TWLSFrm = class(TBasicStatsParamsForm) //TBasicStatsReportAndChartForm)
|
2020-03-30 18:01:44 +00:00
|
|
|
DepInBtn: TBitBtn;
|
|
|
|
DepOutBtn: TBitBtn;
|
|
|
|
IndInBtn: TBitBtn;
|
|
|
|
IndOutBtn: TBitBtn;
|
2020-10-11 22:31:17 +00:00
|
|
|
PageControl: TPageControl;
|
|
|
|
OLSPage: TTabSheet;
|
2020-10-12 13:43:51 +00:00
|
|
|
ResRegPageControl: TPageControl;
|
2020-10-11 22:31:17 +00:00
|
|
|
ResidualsRegPage: TTabSheet;
|
2020-10-12 13:43:51 +00:00
|
|
|
ResRegReportPage: TTabSheet;
|
2020-10-11 22:31:17 +00:00
|
|
|
WLSPage: TTabSheet;
|
2020-03-30 18:01:44 +00:00
|
|
|
WghtInBtn: TBitBtn;
|
|
|
|
WghtOutBtn: TBitBtn;
|
|
|
|
OLSChk: TCheckBox;
|
|
|
|
PlotChk: TCheckBox;
|
|
|
|
RegResChk: TCheckBox;
|
|
|
|
SaveChk: TCheckBox;
|
|
|
|
WeightChk: TCheckBox;
|
|
|
|
OriginChk: TCheckBox;
|
|
|
|
UserWghtsChk: TCheckBox;
|
|
|
|
Origin2Chk: TCheckBox;
|
|
|
|
DepVarEdit: TEdit;
|
|
|
|
WghtVarEdit: TEdit;
|
2020-10-11 22:31:17 +00:00
|
|
|
OptionsGroup: TGroupBox;
|
2020-03-30 18:01:44 +00:00
|
|
|
Label1: TLabel;
|
|
|
|
Label2: TLabel;
|
|
|
|
Label3: TLabel;
|
|
|
|
Label4: TLabel;
|
|
|
|
IndVarList: TListBox;
|
|
|
|
VarList: TListBox;
|
|
|
|
procedure DepInBtnClick(Sender: TObject);
|
|
|
|
procedure DepOutBtnClick(Sender: TObject);
|
|
|
|
procedure IndInBtnClick(Sender: TObject);
|
|
|
|
procedure IndOutBtnClick(Sender: TObject);
|
2020-10-11 22:31:17 +00:00
|
|
|
procedure IndVarListDblClick(Sender: TObject);
|
|
|
|
procedure VarListDblClick(Sender: TObject);
|
2020-03-30 18:01:44 +00:00
|
|
|
procedure VarListSelectionChange(Sender: TObject; User: boolean);
|
|
|
|
procedure WghtInBtnClick(Sender: TObject);
|
|
|
|
procedure WghtOutBtnClick(Sender: TObject);
|
|
|
|
|
|
|
|
private
|
2020-10-11 22:31:17 +00:00
|
|
|
OLSReportFrame: TReportFrame;
|
|
|
|
ResidualsRegReportFrame: TReportFrame;
|
|
|
|
WLSReportFrame: TReportFrame;
|
2020-10-12 13:43:51 +00:00
|
|
|
|
|
|
|
procedure CreateOrGetChartFrame(AColIndex: Integer; AVarName: String;
|
|
|
|
out AMemo: TMemo; out AChartFrame: TChartFrame);
|
|
|
|
|
|
|
|
function GetPageCaption(AVarName: String): String;
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
procedure PredictIt(ColNoSelected: IntDyneVec; NoVars: integer;
|
|
|
|
Means, StdDevs, BetaWeights: DblDyneVec;
|
|
|
|
StdErrEst: double; NoIndepVars: integer);
|
|
|
|
|
2020-10-12 13:43:51 +00:00
|
|
|
procedure PlotXY(AChartFrame: TChartFrame; const XPoints, YPoints, UpConf, LowConf: DblDyneVec;
|
|
|
|
ConfBand, XMean, YMean, R, Slope, Intercept: Double; XLabel, YLabel: String);
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
procedure PlotXY(Xpoints, Ypoints, UpConf, LowConf: DblDyneVec;
|
|
|
|
ConfBand, Xmean, Ymean, R, Slope, Intercept: double;
|
|
|
|
Xmax, Xmin, Ymax, Ymin: double;
|
|
|
|
N: integer; XLabel, YLabel: string);
|
|
|
|
|
|
|
|
protected
|
|
|
|
procedure AdjustConstraints; override;
|
|
|
|
procedure Compute; override;
|
|
|
|
procedure UpdateBtnStates; override;
|
|
|
|
function Validate(out AMsg: String; out AControl: TWinControl): Boolean; override;
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
public
|
2020-10-11 22:31:17 +00:00
|
|
|
constructor Create(AOwner: TComponent); override;
|
|
|
|
procedure Reset; override;
|
|
|
|
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
var
|
|
|
|
WLSFrm: TWLSFrm;
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
implementation
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
{$R *.lfm}
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
uses
|
2020-10-12 13:43:51 +00:00
|
|
|
TAChartUtils, TALegend,
|
2020-10-11 22:31:17 +00:00
|
|
|
Utils, GridProcs, MathUnit;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
{ TWLSFrm }
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
constructor TWLSFrm.Create(AOwner: TComponent);
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-11 22:31:17 +00:00
|
|
|
inherited;
|
2020-03-30 18:01:44 +00:00
|
|
|
if BlankFrm = nil then Application.CreateForm(TBlankFrm, BlankFrm);
|
|
|
|
if DictionaryFrm = nil then Application.CreateForm(TDictionaryFrm, DictionaryFrm);
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
OLSReportFrame := TReportFrame.Create(self);
|
|
|
|
OLSReportFrame.Name := '';
|
|
|
|
OLSReportFrame.Parent := OLSPage;
|
|
|
|
OLSReportFrame.Align := alClient;
|
|
|
|
OLSReportFrame.BorderSpacing.Left := 0;
|
|
|
|
OLSReportFrame.BorderSpacing.Top := 0;
|
|
|
|
OLSReportFrame.BorderSpacing.Bottom := 0;
|
|
|
|
OLSReportFrame.BorderSpacing.Right := 0;
|
|
|
|
InitToolbar(OLSReportFrame.ReportToolbar, tpRight);
|
|
|
|
|
|
|
|
ResidualsRegReportFrame := TReportFrame.Create(self);
|
|
|
|
ResidualsRegReportFrame.Name := '';
|
2020-10-12 13:43:51 +00:00
|
|
|
ResidualsRegReportFrame.Parent := ResRegReportPage;
|
2020-10-11 22:31:17 +00:00
|
|
|
ResidualsRegReportFrame.Align := alClient;
|
|
|
|
ResidualsRegReportFrame.BorderSpacing.Left := 0;
|
|
|
|
ResidualsRegReportFrame.BorderSpacing.Top := 0;
|
|
|
|
ResidualsRegReportFrame.BorderSpacing.Bottom := 0;
|
|
|
|
ResidualsRegReportFrame.BorderSpacing.Right := 0;
|
|
|
|
InitToolbar(ResidualsRegReportFrame.ReportToolbar, tpRight);
|
|
|
|
|
|
|
|
WLSReportFrame := TReportFrame.Create(self);
|
|
|
|
WLSReportFrame.Name := '';
|
|
|
|
WLSReportFrame.Parent := WLSPage;
|
|
|
|
WLSReportFrame.Align := alClient;
|
|
|
|
WLSReportFrame.BorderSpacing.Left := 0;
|
|
|
|
WLSReportFrame.BorderSpacing.Top := 0;
|
|
|
|
WLSReportFrame.BorderSpacing.Bottom := 0;
|
|
|
|
WLSReportFrame.BorderSpacing.Right := 0;
|
|
|
|
InitToolbar(WLSReportFrame.ReportToolbar, tpRight);
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
procedure TWLSFrm.AdjustConstraints;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-11 22:31:17 +00:00
|
|
|
ParamsPanel.Constraints.MinHeight := DepInBtn.Top + (IndOutBtn.Top - DepInBtn.Top)*2 + DepInBtn.Top +
|
|
|
|
OptionsGroup.Height + ButtonBevel.Height + CloseBtn.BorderSpacing.Top + CloseBtn.Height;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
ParamsPanel.Constraints.MinWidth := OptionsGroup.Width;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
procedure TWLSFrm.Compute;
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-10-11 22:31:17 +00:00
|
|
|
i, ii, j, Noindep, DepCol, WghtCol, olddepcol, NCases, pos, col: integer;
|
|
|
|
IndepCols: IntDyneVec = nil;
|
|
|
|
RowLabels: StrDyneVec = nil;
|
|
|
|
X, Y: double;
|
|
|
|
Means: DblDyneVec = nil;
|
|
|
|
Variances: DblDyneVec = nil;
|
|
|
|
StdDevs: DblDyneVec = nil;
|
|
|
|
BWeights: DblDyneVec = nil;
|
|
|
|
BetaWeights: DblDyneVec = nil;
|
|
|
|
BStdErrs: DblDyneVec = nil;
|
|
|
|
BtTests: DblDyneVec = nil;
|
|
|
|
tProbs: DblDyneVec = nil;
|
|
|
|
PrintDesc: boolean = true;
|
|
|
|
Xpoints: DblDyneVec = nil;
|
|
|
|
Ypoints: DblDyneVec = nil;
|
|
|
|
upConf: DblDyneVec = nil;
|
|
|
|
lowConf: DblDyneVec = nil;
|
|
|
|
Xmax, Xmin, Ymax, Ymin, Xmean, Ymean, Xvariance, Yvariance, R: double;
|
|
|
|
temp, SEPred, Slope, Intercept, DF, SSx, t, ConfBand, sedata: double;
|
|
|
|
Xstddev, Ystddev, predicted: double;
|
|
|
|
ColNoSelected: IntDyneVec = nil;
|
|
|
|
XLabel, YLabel: string;
|
|
|
|
N, Xcol, Ycol, NoSelected: integer;
|
|
|
|
lReport: TStrings;
|
|
|
|
StdErrEst: Double = 0.0;
|
|
|
|
R2: Double = 0.0;
|
|
|
|
errorcode: Boolean = false;
|
|
|
|
C: TWinControl;
|
|
|
|
msg: String;
|
2020-10-12 13:43:51 +00:00
|
|
|
chartFrame: TChartFrame;
|
|
|
|
memo: TMemo;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-11 22:31:17 +00:00
|
|
|
if not Validate(msg, C) then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-11 22:31:17 +00:00
|
|
|
C.SetFocus;
|
|
|
|
ErrorMsg(msg);
|
|
|
|
exit;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
PrintDesc := true;
|
|
|
|
|
|
|
|
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);
|
|
|
|
SetLength(RowLabels, NoVariables + 2);
|
|
|
|
SetLength(IndepCols, NoVariables + 2);
|
2020-10-12 13:43:51 +00:00
|
|
|
// SetLength(Xpoints, NoCases + 1);
|
|
|
|
// SetLength(Ypoints, NoCases + 1);
|
|
|
|
// SetLength(UpConf, NoCases + 1);
|
|
|
|
// SetLength(lowConf, NoCases + 1);
|
2020-03-30 18:01:44 +00:00
|
|
|
SetLength(ColNoSelected, 2);
|
|
|
|
|
|
|
|
lReport := TStringList.Create;
|
|
|
|
try
|
|
|
|
NCases := NoCases;
|
2020-10-11 22:31:17 +00:00
|
|
|
NoIndep := IndVarList.Items.Count;
|
|
|
|
|
2020-10-12 13:43:51 +00:00
|
|
|
// wp: This SetLength crashes...
|
2020-10-11 22:31:17 +00:00
|
|
|
// SetLength(IndepCols, NoIndep+1); // +1 because the dep col will be stuffed in there, too
|
|
|
|
// SetLength(RowLabels, NoIndep);
|
|
|
|
|
|
|
|
depCol := GetVariableIndex(OS3MainFrm.DataGrid, DepVarEdit.Text);
|
|
|
|
wghtCol := GetVariableIndex(OS3MainFrm.DataGrid, WghtVarEdit.Text);
|
|
|
|
for i := 0 to NoIndep-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-11 22:31:17 +00:00
|
|
|
IndepCols[i] := GetVariableIndex(OS3MainFrm.DataGrid, IndVarList.Items[i]);
|
|
|
|
if IndepCols[i] = -1 then begin
|
|
|
|
ErrorMsg('Dependent variable %s not found.', [IndVarList.Items[i]]);
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
RowLabels[i] := IndVarList.Items[i];
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
{
|
2020-03-30 18:01:44 +00:00
|
|
|
WghtCol := 0;
|
|
|
|
for i := 0 to NoVariables - 1 do
|
|
|
|
begin
|
|
|
|
if (OS3MainFrm.DataGrid.Cells[i+1,0] = DepVarEdit.Text) then DepCol := i+1;
|
|
|
|
if (OS3MainFrm.DataGrid.Cells[i+1,0] = WghtVarEdit.Text) then WghtCol := i+1;
|
|
|
|
for j := 0 to Noindep - 1 do
|
|
|
|
begin
|
|
|
|
if (OS3MainFrm.DataGrid.Cells[i+1,0] = IndVarList.Items.Strings[j]) then
|
|
|
|
begin
|
|
|
|
IndepCols[j] := i+1;
|
|
|
|
RowLabels[j] := IndVarList.Items.Strings[j];
|
|
|
|
end;
|
|
|
|
end; // next j
|
|
|
|
end; // next i
|
|
|
|
|
|
|
|
if (DepCol = 0) then
|
|
|
|
begin
|
2020-10-11 22:31:17 +00:00
|
|
|
ErrorMsg('No dependent variable selected.');
|
2020-03-30 18:01:44 +00:00
|
|
|
exit;
|
|
|
|
end;
|
2020-10-11 22:31:17 +00:00
|
|
|
}
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
{ wp: I think this is not correct: The column index is the last one in this
|
|
|
|
call. And why is row 0 checked?
|
2020-03-30 18:01:44 +00:00
|
|
|
// check variable types
|
2020-10-11 22:31:17 +00:00
|
|
|
if not ValidValue(OS3MainFrm.DataGrid, DepCol, 0) then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-11 22:31:17 +00:00
|
|
|
ErrorMsg('Incorrect dependent variable type.');
|
2020-03-30 18:01:44 +00:00
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
if (WghtCol > -1) then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-11 22:31:17 +00:00
|
|
|
if not ValidValue(OS3MainFrm.DataGrid, WghtCol, 0) then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-11 22:31:17 +00:00
|
|
|
ErrorMsg('Incorrect weight variable type.');
|
2020-03-30 18:01:44 +00:00
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
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;
|
|
|
|
}
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
IndepCols[NoIndep] := depCol;
|
|
|
|
oldDepCol := DepCol; // save dependent column so we can reuse DepCol
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
// Get OLS regression
|
|
|
|
if OLSChk.Checked then
|
|
|
|
begin
|
|
|
|
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);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
// Get predicted z score, residual z score, predicted raw score,
|
|
|
|
// residual raw score and squared raw residual score. Place in the DataGrid
|
2020-10-11 22:31:17 +00:00
|
|
|
PredictIt(IndepCols, Noindep+1, Means, StdDevs, BetaWeights, stderrest, NoIndep);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
OLSReportFrame.DisplayReport(lReport);
|
|
|
|
lReport.Clear;
|
|
|
|
{
|
2020-03-30 18:01:44 +00:00
|
|
|
lReport.Add('');
|
2020-10-11 22:31:17 +00:00
|
|
|
lReport.Add(DIVIDER);
|
2020-03-30 18:01:44 +00:00
|
|
|
lReport.Add('');
|
2020-10-11 22:31:17 +00:00
|
|
|
}
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
if RegResChk.Checked and OLSChk.Checked then
|
|
|
|
begin
|
|
|
|
// 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;
|
|
|
|
{
|
|
|
|
lReport.Add(DIVIDER);
|
|
|
|
lReport.Add('');
|
|
|
|
}
|
|
|
|
// FReportFrame.DisplayReport(lReport);
|
|
|
|
// lReport.Clear;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
if WeightChk.Checked and RegResChk.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;
|
2020-10-12 13:43:51 +00:00
|
|
|
for j := 0 to NoIndep - 1 do
|
2020-10-11 22:31:17 +00:00
|
|
|
begin
|
|
|
|
pos := IndepCols[j];
|
|
|
|
X := StrToFloat(OS3MainFrm.DataGrid.Cells[pos,i]);
|
|
|
|
predicted := predicted + BWeights[j] * X;
|
|
|
|
end;
|
|
|
|
predicted := predicted + BWeights[Noindep];
|
|
|
|
predicted := abs(predicted);
|
2020-10-12 13:43:51 +00:00
|
|
|
OS3MainFrm.DataGrid.Cells[col-1,i] := Format('%.3f', [predicted]);
|
2020-10-11 22:31:17 +00:00
|
|
|
if (predicted > 0.0) then
|
|
|
|
predicted := 1.0 / sqrt(predicted)
|
|
|
|
else
|
|
|
|
predicted := 0.0;
|
2020-10-12 13:43:51 +00:00
|
|
|
OS3MainFrm.DataGrid.Cells[col,i] := Format('%.3f', [predicted]);
|
2020-10-11 22:31:17 +00:00
|
|
|
end; // if valid case
|
|
|
|
end; // next i
|
|
|
|
end; // if regresChk
|
|
|
|
|
|
|
|
// Now, plot squared residuals against each independent variable
|
2020-10-12 13:43:51 +00:00
|
|
|
if RegResChk.Checked then
|
2020-10-11 22:31:17 +00:00
|
|
|
begin
|
|
|
|
xCol := DepCol;
|
|
|
|
for ii := 0 to NoIndep - 1 do
|
|
|
|
begin
|
2020-10-12 13:43:51 +00:00
|
|
|
SetLength(xPoints, NoCases);
|
|
|
|
SetLength(yPoints, NoCases);
|
2020-10-11 22:31:17 +00:00
|
|
|
yCol := IndepCols[ii];
|
|
|
|
N := 0;
|
|
|
|
ColNoSelected[0] := xCol;
|
|
|
|
ColNoSelected[1] := yCol;
|
|
|
|
NoSelected := 2;
|
|
|
|
XLabel := OS3MainFrm.DataGrid.Cells[Xcol,0];
|
|
|
|
YLabel := OS3MainFrm.DataGrid.Cells[Ycol,0];
|
|
|
|
Xmax := -1.0e308;
|
|
|
|
Xmin := 1.0e308;
|
|
|
|
Ymax := -1.0e308;
|
|
|
|
Ymin := 1.0e308;
|
|
|
|
Xmean := 0.0;
|
|
|
|
Ymean := 0.0;
|
|
|
|
Xvariance := 0.0;
|
|
|
|
Yvariance := 0.0;
|
|
|
|
R := 0.0;
|
|
|
|
for i := 1 to NoCases do
|
|
|
|
begin
|
|
|
|
if (not DataProcs.GoodRecord(i,NoSelected,ColNoSelected)) then continue;
|
|
|
|
X := StrToFloat(OS3MainFrm.DataGrid.Cells[Xcol,i]);
|
|
|
|
Y := StrToFloat(OS3MainFrm.DataGrid.Cells[Ycol,i]);
|
|
|
|
Xpoints[N] := X;
|
|
|
|
Ypoints[N] := Y;
|
|
|
|
if (X > Xmax) then Xmax := X;
|
|
|
|
if (X < Xmin) then Xmin := X;
|
|
|
|
if (Y > Ymax) then Ymax := Y;
|
|
|
|
if (Y < Ymin) then Ymin := Y;
|
|
|
|
Xmean := Xmean + X;
|
|
|
|
Ymean := Ymean + Y;
|
|
|
|
Xvariance := Xvariance + X * X;
|
|
|
|
Yvariance := Yvariance + Y * Y;
|
|
|
|
R := R + X * Y;
|
2020-10-12 13:43:51 +00:00
|
|
|
N := N + 1;
|
2020-10-11 22:31:17 +00:00
|
|
|
end;
|
2020-10-12 13:43:51 +00:00
|
|
|
SetLength(xPoints, N);
|
|
|
|
SetLength(yPoints, N);
|
2020-10-11 22:31:17 +00:00
|
|
|
|
|
|
|
// sort on X
|
|
|
|
SortOnX(xPoints, yPoints);
|
|
|
|
|
|
|
|
// calculate statistics
|
|
|
|
Xvariance := Xvariance - Xmean * Xmean / N;
|
|
|
|
SSx := Xvariance;
|
|
|
|
Xvariance := Xvariance / (N - 1);
|
|
|
|
Xstddev := sqrt(Xvariance);
|
|
|
|
|
|
|
|
Yvariance := Yvariance - Ymean * Ymean / N;
|
|
|
|
Yvariance := Yvariance / (N - 1);
|
|
|
|
Ystddev := sqrt(Yvariance);
|
|
|
|
|
|
|
|
R := R - Xmean * Ymean / N;
|
|
|
|
R := R / (N - 1);
|
|
|
|
R := R / (Xstddev * Ystddev);
|
|
|
|
|
|
|
|
SEPred := sqrt(1.0 - R * R) * Ystddev;
|
|
|
|
SEPred := SEPred * sqrt((N - 1) / (N - 2));
|
|
|
|
Xmean := Xmean / N;
|
|
|
|
Ymean := Ymean / N;
|
|
|
|
Slope := R * Ystddev / Xstddev;
|
|
|
|
Intercept := Ymean - Slope * Xmean;
|
|
|
|
|
|
|
|
// Now, print the descriptive statistics if requested
|
2020-10-12 13:43:51 +00:00
|
|
|
lReport.Clear;
|
2020-10-11 22:31:17 +00:00
|
|
|
lReport.Add('Data file: %s', [OS3MainFrm.FileNameEdit.Text]);
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('Variables:');
|
|
|
|
lReport.Add(' X: %s', [OS3MainFrm.DataGrid.Cells[xCol, 0]]);
|
|
|
|
lReport.Add(' Y: %s', [OS3MainFrm.DataGrid.Cells[yCol, 0]]);
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('Variable Mean Variance Std.Dev.');
|
|
|
|
lReport.Add('---------- -------- -------- --------');
|
|
|
|
lReport.Add('%-10s %8.2f %8.2f %8.2f', [OS3MainFrm.DataGrid.Cells[xCol, 0], XMean, XVariance, XStdDev]);
|
|
|
|
lReport.Add('%-10s %8.2f %8.2f %8.2f', [OS3MainFrm.DataGrid.Cells[ycol, 0], YMean, YVariance, YStdDev]);
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('Correlation: %8.4f', [R]);
|
|
|
|
lReport.Add('Slope: %8.2f', [Slope]);
|
|
|
|
lReport.Add('Intercept: %8.2f', [Intercept]);
|
|
|
|
lReport.Add('Standard Error of Estimate: %8.2f', [SEPred]);
|
|
|
|
lReport.Add('Number of good cases: %8d', [N]);
|
|
|
|
|
2020-10-12 13:43:51 +00:00
|
|
|
// Get upper and lower confidence points for each X value
|
|
|
|
SetLength(UpConf, N);
|
|
|
|
SetLength(LowConf, N);
|
2020-10-11 22:31:17 +00:00
|
|
|
ConfBand := 0.95;
|
|
|
|
DF := N - 2;
|
|
|
|
t := inverset(ConfBand,DF);
|
2020-10-12 13:43:51 +00:00
|
|
|
for i := 0 to N-1 do
|
2020-10-11 22:31:17 +00:00
|
|
|
begin
|
|
|
|
X := Xpoints[i];
|
|
|
|
predicted := Slope * X + Intercept;
|
|
|
|
sedata := SEPred * sqrt(1.0 + (1.0 / N) + ((X - Xmean) * (X - Xmean) / SSx));
|
|
|
|
UpConf[i] := predicted + (t * sedata);
|
|
|
|
lowConf[i] := predicted - (t * sedata);
|
|
|
|
if (UpConf[i] > Ymax) then Ymax := UpConf[i];
|
|
|
|
if (lowConf[i] < Ymin) then Ymin := lowConf[i];
|
|
|
|
end;
|
|
|
|
|
2020-10-12 13:43:51 +00:00
|
|
|
// 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;
|
2020-10-11 22:31:17 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
// FReportFrame.DisplayReport(lReport);
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
if not UserWghtsChk.Checked then
|
|
|
|
begin
|
|
|
|
// Weight variables and do OLS regression on weighted variables
|
|
|
|
DepCol := olddepcol;
|
|
|
|
IndepCols[Noindep] := DepCol;
|
|
|
|
for i := 1 to NoCases do
|
|
|
|
begin
|
|
|
|
Y := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[NoVariables,i])); // weight
|
|
|
|
for j := 0 to Noindep do
|
|
|
|
begin
|
|
|
|
pos := IndepCols[j];
|
|
|
|
X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[pos,i]));
|
|
|
|
X := X * Y;
|
|
|
|
OS3MainFrm.DataGrid.Cells[pos,i] := FloatToStr(X);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
// get means of variables and subtract from the values
|
|
|
|
if OriginChk.Checked then
|
|
|
|
begin
|
|
|
|
for j := 0 to Noindep do
|
|
|
|
begin
|
|
|
|
Means[j] := 0.0;
|
|
|
|
NCases := 0;
|
|
|
|
pos := IndepCols[j];
|
|
|
|
for i := 1 to NoCases do
|
|
|
|
begin
|
|
|
|
if (DataProcs.ValidValue(i,pos)) then
|
|
|
|
begin
|
|
|
|
Means[j] := Means[j] + StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[pos,i]));
|
|
|
|
NCases := NCases + 1;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
Means[j] := Means[j] / NCases;
|
|
|
|
for i := 1 to NoCases do
|
|
|
|
begin
|
|
|
|
if (DataProcs.ValidValue(i,pos)) then
|
|
|
|
begin
|
|
|
|
X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[pos,i]));
|
|
|
|
X := X - Means[j];
|
|
|
|
OS3MainFrm.DataGrid.Cells[pos,i] := FloatToStr(X);
|
|
|
|
end;
|
|
|
|
end; // next i
|
|
|
|
end; // next j
|
|
|
|
end; // if origin checked
|
|
|
|
|
|
|
|
lReport.Clear;
|
|
|
|
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,
|
|
|
|
NCases, errorcode, PrintDesc, lReport);
|
|
|
|
|
|
|
|
WLSReportFrame.DisplayReport(lReport);
|
|
|
|
lReport.Clear;
|
|
|
|
end // if useweightschk checked
|
|
|
|
else
|
|
|
|
// use the weights entered by the user
|
|
|
|
if (UserWghtsChk.Checked) then
|
|
|
|
begin
|
|
|
|
// Weight variables and do OLS regression on weighted variables
|
|
|
|
DepCol := olddepcol;
|
|
|
|
IndepCols[Noindep] := DepCol;
|
|
|
|
for i := 1 to NoCases do
|
|
|
|
begin
|
|
|
|
Y := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[WghtCol,i])); // weight
|
|
|
|
for j := 0 to Noindep do
|
|
|
|
begin
|
|
|
|
pos := IndepCols[j];
|
|
|
|
X := StrToFloat(OS3MainFrm.DataGrid.Cells[pos,i]);
|
|
|
|
X := X * Y;
|
|
|
|
OS3MainFrm.DataGrid.Cells[pos,i] := FloatToStr(X);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
if (OriginChk.Checked) then // get means of variables and subtract from the values
|
|
|
|
begin
|
|
|
|
for j := 0 to Noindep do
|
|
|
|
begin
|
|
|
|
Means[j] := 0.0;
|
|
|
|
NCases := 0;
|
|
|
|
pos := IndepCols[j];
|
|
|
|
for i := 1 to NoCases do
|
|
|
|
begin
|
|
|
|
if (DataProcs.ValidValue(i,pos)) then
|
|
|
|
begin
|
|
|
|
Means[j] := Means[j] + StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[pos,i]));
|
|
|
|
NCases := NCases + 1;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
Means[j] := Means[j] / NCases;
|
|
|
|
for i := 1 to NoCases do
|
|
|
|
begin
|
|
|
|
if (DataProcs.ValidValue(i,pos)) then
|
|
|
|
begin
|
|
|
|
X := StrToFloat(OS3MainFrm.DataGrid.Cells[pos,i]);
|
|
|
|
X := X - Means[j];
|
|
|
|
OS3MainFrm.DataGrid.Cells[pos,i] := FloatToStr(X);
|
|
|
|
end;
|
|
|
|
end; // next i
|
|
|
|
end; // next j
|
|
|
|
end; // if origin checked
|
|
|
|
|
|
|
|
lReport.Clear;
|
|
|
|
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,
|
|
|
|
NCases, errorcode, PrintDesc, lReport);
|
|
|
|
|
|
|
|
WLSReportFrame.DisplayReport(lReport);
|
|
|
|
lReport.Clear;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
finally
|
|
|
|
lReport.Free;
|
2020-10-11 22:31:17 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-10-12 13:43:51 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
procedure TWLSFrm.DepInBtnClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
index: integer;
|
|
|
|
begin
|
|
|
|
index := VarList.ItemIndex;
|
|
|
|
if (index > -1) and (DepVarEdit.Text = '') then
|
|
|
|
begin
|
|
|
|
DepVarEdit.Text := VarList.Items[index];
|
|
|
|
VarList.Items.Delete(index);
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TWLSFrm.DepOutBtnClick(Sender: TObject);
|
|
|
|
begin
|
|
|
|
if (DepVarEdit.Text <> '') then
|
|
|
|
begin
|
|
|
|
VarList.Items.Add(DepVarEdit.Text);
|
|
|
|
DepVarEdit.Text := '';
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-10-12 13:43:51 +00:00
|
|
|
function TWLSFrm.GetPageCaption(AVarName: String): String;
|
|
|
|
begin
|
|
|
|
Result := 'Plot of ' + AVarName;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
procedure TWLSFrm.IndInBtnClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
i: integer;
|
|
|
|
begin
|
|
|
|
i := 0;
|
|
|
|
while (i < VarList.Items.Count) do
|
|
|
|
begin
|
|
|
|
if (VarList.Selected[i]) then
|
|
|
|
begin
|
|
|
|
IndVarList.Items.Add(VarList.Items[i]);
|
|
|
|
VarList.Items.Delete(i);
|
|
|
|
i := 0;
|
|
|
|
end else
|
|
|
|
inc(i);
|
|
|
|
end;
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TWLSFrm.IndOutBtnClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
i: integer;
|
|
|
|
begin
|
|
|
|
i := 0;
|
|
|
|
while (i < IndVarList.Items.Count) do
|
|
|
|
begin
|
|
|
|
if IndVarlist.Selected[i] then
|
|
|
|
begin
|
|
|
|
VarList.Items.Add(IndVarList.Items[i]);
|
|
|
|
IndVarlist.Items.Delete(i);
|
|
|
|
i := 0;
|
|
|
|
end else
|
|
|
|
inc(i);
|
|
|
|
end;
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
|
|
|
|
procedure TWLSFrm.IndVarListDblClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
index: Integer;
|
|
|
|
begin
|
|
|
|
index := IndVarList.ItemIndex;
|
|
|
|
if index > -1 then
|
|
|
|
begin
|
|
|
|
VarList.Items.Add(IndVarList.Items[index]);
|
|
|
|
IndVarlist.Items.Delete(index);
|
|
|
|
UpdateBtnStates;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-10-12 13:43:51 +00:00
|
|
|
{ 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 }
|
2020-03-30 18:01:44 +00:00
|
|
|
procedure TWLSFrm.PredictIt(ColNoSelected: IntDyneVec; NoVars: integer;
|
2020-10-12 13:43:51 +00:00
|
|
|
Means, StdDevs, BetaWeights: DblDyneVec; StdErrEst: double; NoIndepVars: integer);
|
2020-10-11 22:31:17 +00:00
|
|
|
var
|
2020-10-12 13:43:51 +00:00
|
|
|
col, i, j, k, Index: integer;
|
|
|
|
predicted, zpredicted, z1, z2, resid, residsqr: double;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-10-12 13:43:51 +00:00
|
|
|
col := NoVariables + 1;
|
2020-03-30 18:01:44 +00:00
|
|
|
// NoVariables := col;
|
2020-10-12 13:43:51 +00:00
|
|
|
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';
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-10-12 13:43:51 +00:00
|
|
|
col := NoVariables + 1;
|
2020-03-30 18:01:44 +00:00
|
|
|
// NoVariables := col;
|
2020-10-12 13:43:51 +00:00
|
|
|
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('%.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('%.3f',[predicted]);
|
|
|
|
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.';
|
|
|
|
|
|
|
|
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;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-10-12 13:43:51 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
procedure TWLSFrm.PlotXY(Xpoints, Ypoints, UpConf, LowConf : DblDyneVec;
|
|
|
|
ConfBand, Xmean, Ymean, R, Slope, Intercept : double;
|
|
|
|
Xmax, Xmin, Ymax, Ymin : double;
|
|
|
|
N : integer; XLabel, YLabel : string);
|
|
|
|
VAR
|
|
|
|
i, xpos, ypos, hleft, hright, vtop, vbottom, imagewide : integer;
|
|
|
|
vhi, hwide, offset, strhi, imagehi : integer;
|
|
|
|
valincr, Yvalue, Xvalue, value : double;
|
|
|
|
Title, outline : string;
|
|
|
|
|
|
|
|
begin
|
|
|
|
BlankFrm.Image1.Canvas.Clear;
|
|
|
|
Title := 'X versus Y PLOT Using File: ' + OS3MainFrm.FileNameEdit.Text;
|
|
|
|
BlankFrm.Caption := Title;
|
|
|
|
imagewide := BlankFrm.Image1.Width;
|
|
|
|
imagehi := BlankFrm.Image1.Height;
|
|
|
|
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
|
|
|
|
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
|
|
|
|
BlankFrm.Image1.Canvas.Rectangle(0,0,imagewide,imagehi);
|
|
|
|
BlankFrm.Image1.Canvas.FloodFill(0,0,clWhite,fsBorder);
|
|
|
|
vtop := 20;
|
|
|
|
vbottom := round(imagehi) - 80;
|
|
|
|
vhi := vbottom - vtop;
|
|
|
|
hleft := 100;
|
|
|
|
hright := imagewide - 80;
|
|
|
|
hwide := hright - hleft;
|
|
|
|
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
|
|
|
|
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
|
|
|
|
|
|
|
|
// Draw chart border
|
|
|
|
BlankFrm.Image1.Canvas.Rectangle(0,0,imagewide,imagehi);
|
|
|
|
|
|
|
|
// draw Means
|
|
|
|
ypos := round(vhi * ( (Ymax - Ymean) / (Ymax - Ymin)));
|
|
|
|
ypos := ypos + vtop;
|
|
|
|
xpos := hleft;
|
|
|
|
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
|
|
|
|
xpos := hright;
|
|
|
|
BlankFrm.Image1.Canvas.Pen.Color := clGreen;
|
|
|
|
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
|
|
|
|
Title := 'MEAN ';
|
|
|
|
Title := Title + YLabel;
|
|
|
|
strhi := BlankFrm.Image1.Canvas.TextHeight(Title);
|
|
|
|
ypos := ypos - strhi div 2;
|
|
|
|
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
|
|
|
|
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
|
|
|
|
|
|
|
|
xpos := round(hwide * ( (Xmean - Xmin) / (Xmax - Xmin)));
|
|
|
|
xpos := xpos + hleft;
|
|
|
|
ypos := vtop;
|
|
|
|
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
|
|
|
|
ypos := vbottom;
|
|
|
|
BlankFrm.Image1.Canvas.Pen.Color := clGreen;
|
|
|
|
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
|
|
|
|
Title := 'MEAN ';
|
|
|
|
Title := Title + XLabel;
|
|
|
|
strhi := BlankFrm.Image1.Canvas.TextWidth(Title);
|
|
|
|
xpos := xpos - strhi div 2;
|
|
|
|
ypos := vtop - BlankFrm.Image1.Canvas.TextHeight(Title);
|
|
|
|
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
|
|
|
|
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
|
|
|
|
|
|
|
|
// draw slope line
|
|
|
|
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
|
|
|
|
Yvalue := (Xpoints[1] * Slope) + Intercept; // predicted score
|
|
|
|
ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin)));
|
|
|
|
ypos := ypos + vtop;
|
|
|
|
xpos := round(hwide * ( (Xpoints[1]- Xmin) / (Xmax - Xmin)));
|
|
|
|
xpos := xpos + hleft;
|
|
|
|
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
|
|
|
|
Yvalue := (Xpoints[N] * Slope) + Intercept; // predicted score
|
|
|
|
ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin)));
|
|
|
|
ypos := ypos + vtop;
|
|
|
|
xpos := round(hwide * ( (Xpoints[N] - Xmin) / (Xmax - Xmin)));
|
|
|
|
xpos := xpos + hleft;
|
|
|
|
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
|
|
|
|
|
|
|
|
// draw horizontal axis
|
|
|
|
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
|
|
|
|
BlankFrm.Image1.Canvas.MoveTo(hleft,vbottom);
|
|
|
|
BlankFrm.Image1.Canvas.LineTo(hright,vbottom);
|
|
|
|
valincr := (Xmax - Xmin) / 10.0;
|
|
|
|
for i := 1 to 11 do
|
|
|
|
begin
|
|
|
|
ypos := vbottom;
|
|
|
|
Xvalue := Xmin + valincr * (i - 1);
|
|
|
|
xpos := round(hwide * ((Xvalue - Xmin) / (Xmax - Xmin)));
|
|
|
|
xpos := xpos + hleft;
|
|
|
|
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
|
|
|
|
ypos := ypos + 10;
|
|
|
|
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
|
|
|
|
outline := format('%6.2f',[Xvalue]);
|
|
|
|
Title := outline;
|
|
|
|
offset := BlankFrm.Image1.Canvas.TextWidth(Title) div 2;
|
|
|
|
xpos := xpos - offset;
|
|
|
|
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
|
|
|
|
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
|
|
|
|
end;
|
|
|
|
xpos := hleft + (hwide div 2) - (BlankFrm.Image1.Canvas.TextWidth(XLabel) div 2);
|
|
|
|
ypos := vbottom + 20;
|
|
|
|
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,XLabel);
|
|
|
|
outline := format('R(X,Y) := %5.3f, Slope := %6.2f, Intercept := %6.2f',
|
|
|
|
[R,Slope,Intercept]);
|
|
|
|
Title := outline;
|
|
|
|
xpos := hleft + (hwide div 2) - (BlankFrm.Image1.Canvas.TextWidth(Title) div 2);
|
|
|
|
ypos := ypos + 15;
|
|
|
|
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
|
|
|
|
|
|
|
|
// Draw vertical axis
|
|
|
|
Title := YLabel;
|
|
|
|
// xpos := hleft - 10 - BlankFrm.Image1.Canvas.TextWidth(Title) / 2;
|
|
|
|
xpos := 10;
|
|
|
|
ypos := vtop - 8 - BlankFrm.Image1.Canvas.TextHeight(Title);
|
|
|
|
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,YLabel);
|
|
|
|
xpos := hleft;
|
|
|
|
ypos := vtop;
|
|
|
|
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
|
|
|
|
ypos := vbottom;
|
|
|
|
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
|
|
|
|
valincr := (Ymax - Ymin) / 10.0;
|
|
|
|
for i := 1 to 11 do
|
|
|
|
begin
|
|
|
|
value := Ymax - ((i-1) * valincr);
|
|
|
|
outline := format('%8.2f',[value]);
|
|
|
|
Title := outline;
|
|
|
|
strhi := BlankFrm.Image1.Canvas.TextHeight(Title);
|
|
|
|
xpos := 10;
|
|
|
|
Yvalue := Ymax - (valincr * (i-1));
|
|
|
|
ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin)));
|
|
|
|
ypos := ypos + vtop - strhi div 2;
|
|
|
|
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
|
|
|
|
xpos := hleft;
|
|
|
|
ypos := ypos + strhi div 2;
|
|
|
|
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
|
|
|
|
xpos := hleft - 10;
|
|
|
|
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
|
|
|
|
end;
|
|
|
|
|
|
|
|
// draw points for x and y pairs
|
2020-10-12 13:43:51 +00:00
|
|
|
for i := 0 to N-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
|
|
|
ypos := round(vhi * ( (Ymax - Ypoints[i]) / (Ymax - Ymin)));
|
|
|
|
ypos := ypos + vtop;
|
|
|
|
xpos := round(hwide * ( (Xpoints[i] - Xmin) / (Xmax - Xmin)));
|
|
|
|
xpos := xpos + hleft;
|
|
|
|
BlankFrm.Image1.Canvas.Brush.Color := clNavy;
|
|
|
|
BlankFrm.Image1.Canvas.Brush.Style := bsSolid;
|
|
|
|
BlankFrm.Image1.Canvas.Pen.Color := clNavy;
|
|
|
|
BlankFrm.Image1.Canvas.Ellipse(xpos,ypos,xpos+5,ypos+5);
|
|
|
|
end;
|
|
|
|
|
|
|
|
// draw confidence bands if requested
|
|
|
|
if not (ConfBand = 0.0) then
|
|
|
|
begin
|
|
|
|
BlankFrm.Image1.Canvas.Pen.Color := clRed;
|
2020-10-12 13:43:51 +00:00
|
|
|
ypos := round(vhi * ((Ymax - UpConf[0]) / (Ymax - Ymin)));
|
2020-03-30 18:01:44 +00:00
|
|
|
ypos := ypos + vtop;
|
2020-10-12 13:43:51 +00:00
|
|
|
xpos := round(hwide * ( (Xpoints[0] - Xmin) / (Xmax - Xmin)));
|
2020-03-30 18:01:44 +00:00
|
|
|
xpos := xpos + hleft;
|
|
|
|
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
|
2020-10-12 13:43:51 +00:00
|
|
|
for i := 1 to N-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
|
|
|
ypos := round(vhi * ((Ymax - UpConf[i]) / (Ymax - Ymin)));
|
|
|
|
ypos := ypos + vtop;
|
|
|
|
xpos := round(hwide * ( (Xpoints[i] - Xmin) / (Xmax - Xmin)));
|
|
|
|
xpos := xpos + hleft;
|
|
|
|
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
|
|
|
|
end;
|
2020-10-12 13:43:51 +00:00
|
|
|
ypos := round(vhi * ((Ymax - LowConf[0]) / (Ymax - Ymin)));
|
2020-03-30 18:01:44 +00:00
|
|
|
ypos := ypos + vtop;
|
2020-10-12 13:43:51 +00:00
|
|
|
xpos := round(hwide * ( (Xpoints[0] - Xmin) / (Xmax - Xmin)));
|
2020-03-30 18:01:44 +00:00
|
|
|
xpos := xpos + hleft;
|
|
|
|
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
|
2020-10-12 13:43:51 +00:00
|
|
|
for i := 1 to N-1 do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
|
|
|
ypos := round(vhi * ((Ymax - LowConf[i]) / (Ymax - Ymin)));
|
|
|
|
ypos := ypos + vtop;
|
|
|
|
xpos := round(hwide * ( (Xpoints[i] - Xmin) / (Xmax - Xmin)));
|
|
|
|
xpos := xpos + hleft;
|
|
|
|
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
procedure TWLSFrm.Reset;
|
|
|
|
var
|
|
|
|
i: integer;
|
|
|
|
begin
|
|
|
|
inherited;
|
|
|
|
|
|
|
|
VarList.Clear;
|
|
|
|
for i := 0 to NoVariables - 1 do
|
|
|
|
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i+1,0]);
|
|
|
|
IndVarList.Clear;
|
|
|
|
|
|
|
|
DepVarEdit.Text := '';
|
|
|
|
WghtVarEdit.Text := '';
|
|
|
|
|
|
|
|
DepInBtn.Enabled := true;
|
|
|
|
DepOutBtn.Enabled := false;
|
|
|
|
IndInBtn.Enabled := true;
|
|
|
|
IndOutBtn.Enabled := false;
|
|
|
|
WghtInBtn.Enabled := true;
|
|
|
|
WghtOutBtn.Enabled := false;
|
|
|
|
OLSChk.Checked := true;
|
|
|
|
PlotChk.Checked := true;
|
|
|
|
RegResChk.Checked := true;
|
|
|
|
WeightChk.Checked := true;
|
|
|
|
UserWghtsChk.Checked := false;
|
|
|
|
OriginChk.Checked := true;
|
|
|
|
Origin2Chk.Checked := true;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
procedure TWLSFrm.UpdateBtnStates;
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
lSelected: Boolean;
|
|
|
|
begin
|
2020-10-11 22:31:17 +00:00
|
|
|
inherited;
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
lSelected := false;
|
|
|
|
for i:=0 to VarList.Items.Count-1 do
|
|
|
|
if Varlist.Selected[i] then
|
|
|
|
begin
|
|
|
|
lSelected := true;
|
|
|
|
break;
|
|
|
|
end;
|
|
|
|
DepInBtn.Enabled := lSelected and (DepVarEdit.Text = '');
|
|
|
|
IndInBtn.Enabled := lSelected;
|
|
|
|
WghtInBtn.Enabled := lSelected and (WghtVarEdit.Text = '');
|
|
|
|
|
|
|
|
lSelected := false;
|
|
|
|
for i:=0 to IndVarList.Items.Count-1 do
|
|
|
|
if IndVarList.Selected[i] then
|
|
|
|
begin
|
|
|
|
lSelected := true;
|
|
|
|
break;
|
|
|
|
end;
|
|
|
|
DepOutBtn.Enabled := (DepVarEdit.Text <> '');
|
|
|
|
IndOutBtn.Enabled := lSelected;
|
|
|
|
WghtOutBtn.Enabled := (WghtVarEdit.Text <> '');
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-10-11 22:31:17 +00:00
|
|
|
function TWLSFrm.Validate(out AMsg: String; out AControl: TWinControl): Boolean;
|
|
|
|
begin
|
|
|
|
Result := false;
|
|
|
|
|
|
|
|
if DepVarEdit.Text = '' then
|
|
|
|
begin
|
|
|
|
AControl := DepVarEdit;
|
|
|
|
AMsg := 'No dependent variable selected.';
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
if IndVarList.Items.Count = 0 then
|
|
|
|
begin
|
|
|
|
AControl := VarList;
|
|
|
|
AMsg := 'No independent variables selected.';
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
Result := true;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TWLSFrm.VarListDblClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
index: Integer;
|
|
|
|
begin
|
|
|
|
index := VarList.ItemIndex;
|
|
|
|
if index > -1 then
|
|
|
|
begin
|
|
|
|
if DepVarEdit.Text = '' then
|
|
|
|
DepVarEdit.Text := VarList.Items[index]
|
|
|
|
else
|
|
|
|
IndVarList.Items.Add(VarList.Items[index]);
|
|
|
|
VarList.Items.Delete(index);
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TWLSFrm.VarListSelectionChange(Sender: TObject; User: boolean);
|
|
|
|
begin
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TWLSFrm.WghtInBtnClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
index: integer;
|
|
|
|
begin
|
|
|
|
index := VarList.ItemIndex;
|
|
|
|
if (index > -1) and (WghtVarEdit.Text = '') then
|
|
|
|
begin
|
|
|
|
WghtVarEdit.Text := VarList.Items[index];
|
|
|
|
VarList.Items.Delete(index);
|
|
|
|
end;
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TWLSFrm.WghtOutBtnClick(Sender: TObject);
|
|
|
|
begin
|
|
|
|
if (WghtVarEdit.Text <> '') then
|
|
|
|
begin
|
|
|
|
VarList.Items.Add(WghtVarEdit.Text);
|
|
|
|
WghtVarEdit.Text := '';
|
|
|
|
end;
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
end.
|
|
|
|
|