Files
lazarus-ccr/applications/lazstats/source/forms/analysis/nonparametric/signtestunit.pas
wp_xxyyzz cfe3a9c460 LazStats: Less hints and warning.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7814 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2020-10-26 18:00:52 +00:00

293 lines
6.7 KiB
ObjectPascal

unit SignTestUnit;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Buttons, ExtCtrls,
MainUnit, FunctionsLib, Globals, BasicStatsReportFormUnit;
type
{ TSignTestFrm }
TSignTestFrm = class(TBasicStatsReportForm)
Var1In: TBitBtn;
Var1Out: TBitBtn;
Var2In: TBitBtn;
Var2Out: TBitBtn;
Var1Edit: TEdit;
Var2Edit: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
VarList: TListBox;
procedure Var1InClick(Sender: TObject);
procedure Var1OutClick(Sender: TObject);
procedure Var2InClick(Sender: TObject);
procedure Var2OutClick(Sender: TObject);
procedure VarListDblClick(Sender: TObject);
procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean);
private
protected
procedure AdjustConstraints; override;
procedure Compute; override;
procedure UpdateBtnStates; override;
function Validate(out AMsg: String; out AControl: TWinControl): boolean; override;
public
procedure Reset; override;
end;
var
SignTestFrm: TSignTestFrm;
implementation
{$R *.lfm}
uses
Math,
GridProcs;
{ TSignTestFrm }
procedure TSignTestFrm.AdjustConstraints;
begin
inherited;
ParamsPanel.Constraints.MinWidth := 4*CloseBtn.Width + 3*CloseBtn.BorderSpacing.Left;
ParamsPanel.Constraints.MinHeight := Var2Out.Top + Var2Out.Height +
ButtonBevel.Height + CloseBtn.Height + CloseBtn.Borderspacing.Top;
end;
procedure TSignTestFrm.Compute;
var
ColNoSelected: IntDyneVec = nil;
DifSigns: IntDyneVec = nil;
i, col1, col2, X, N, A, b, Temp: integer;
p, Q, Probability, z, NoDiff, CorrectedA, x1, x2: double;
SumProb: double;
lReport: TStrings;
begin
SumProb := 0.0;
SetLength(DifSigns, NoCases);
// Get column numbers and labels of variables selected
SetLength(ColNoSelected, 2);
ColNoSelected[0] := GetVariableIndex(OS3MainFrm.DataGrid, Var1Edit.Text);
ColNoSelected[1] := GetVariableIndex(OS3MainFrm.DataGrid, Var2Edit.Text);
p := 0.5;
Q := 0.5;
// Get sign of difference between pairs '(-1 := - ; 0 := no difference; +1 := +
A := 0;
b := 0;
NoDiff := 0.0;
for i := 1 to NoCases do
begin
if (not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected)) then continue;
col1 := ColNoSelected[0];
col2 := ColNoSelected[1];
x1 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col1, i]));
x2 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col2, i]));
if (x1 > x2) then
begin
DifSigns[i-1] := 1;
A := A + 1;
end;
if (x1 < x2) then
begin
DifSigns[i-1] := -1;
b := b + 1;
end;
if (x1 = x2) then
begin
DifSigns[i-1] := 0;
NoDiff := NoDiff + 1.0;
end;
end;
// Show results
lReport := TStringList.Create;
try
lReport.Add('RESULTS FOR THE SIGN TEST');
lReport.Add('');
lReport.Add('Frequency of %d out of %d observed + sign differences.', [A, NoCases]);
lReport.Add('Frequency of %d out of %d observed - sign differences.', [b, NoCases]);
lReport.Add('Frequency of %.0f out of %d observed no differences.', [NoDiff, NoCases]);
lReport.Add('');
lReport.Add('The theoretical proportion expected for +''s or -''s is 0.5 ');
lReport.Add('The test is for the probability of the +''s or -''s (which ever is fewer)');;
lReport.Add('as small or smaller than that observed given the expected proportion.');
lReport.Add('');
// Swap A and B around if A > B
if (A > b) then
begin
Temp := A;
A := b;
b := Temp;
end;
N := A + b;
if (N > 25) then // Use normal distribution approximation
begin
CorrectedA := A;
if (A < N * p) then CorrectedA := A + 0.5;
if (A > N * p) then CorrectedA := A - 0.5;
z := (CorrectedA - N * p) / sqrt(N * p * Q);
lReport.Add('Z value for Normal Distribution approximation: %.3f', [z]);
Probability := ProbZ(z);
lReport.Add('Probability: %.4f', [Probability]);
end
else // Use binomial fomula
begin
X := 0;
while X <= A do
begin
Probability := combos(X, N) * Power(p,X) * Power(Q,(N - X));
lReport.Add('Binary Probability of %3d: %6.4f', [X, Probability]);
SumProb := SumProb + Probability;
X := X + 1;
end;
lReport.Add('Binomial Probability of %d or smaller out of %d: %.4f', [A, N, SumProb]);
end;
FReportFrame.DisplayReport(lReport);
finally
lReport.Free;
end;
end;
procedure TSignTestFrm.Reset;
var
i: integer;
begin
inherited;
Var1Edit.Clear;
Var2Edit.Clear;
VarList.Items.Clear;
for i := 1 to NoVariables do
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
UpdateBtnStates;
end;
function TSignTestFrm.Validate(out AMsg: String; out AControl: TWinControl): boolean;
begin
Result := false;
if Var1Edit.Text = '' then
begin
AMsg := 'Variable 1 not selected.';
AControl := Var1Edit;
exit;
end;
if Var2Edit.Text = '' then
begin
AMsg := 'Variable 2 not selected.';
AControl := Var2Edit;
exit;
end;
Result := true;
end;
procedure TSignTestFrm.Var1InClick(Sender: TObject);
var
index: integer;
begin
index := VarList.ItemIndex;
if (index > -1) and (Var1Edit.Text = '') then
begin
Var1Edit.Text := VarList.Items[index];
VarList.Items.Delete(index);
end;
UpdateBtnStates;
end;
procedure TSignTestFrm.Var1OutClick(Sender: TObject);
begin
if Var1Edit.Text <> '' then
begin
VarList.Items.Add(Var1Edit.Text);
Var1Edit.Text := '';
end;
UpdateBtnStates;
end;
procedure TSignTestFrm.Var2InClick(Sender: TObject);
var
index: integer;
begin
index := VarList.ItemIndex;
if (index > -1) and (Var2Edit.Text = '') then
begin
Var2Edit.Text := VarList.Items[index];
VarList.Items.Delete(index);
end;
UpdateBtnStates;
end;
procedure TSignTestFrm.Var2OutClick(Sender: TObject);
begin
if Var2Edit.Text <> '' then
begin
VarList.Items.Add(Var2Edit.Text);
Var2Edit.Text := '';
end;
UpdateBtnStates;
end;
procedure TSignTestFrm.VarListDblClick(Sender: TObject);
var
index: Integer;
s: String;
begin
index := Varlist.ItemIndex;;
if index > -1 then
begin
s := VarList.Items[index];
if Var1Edit.Text = '' then
Var1Edit.Text := s
else
if Var2Edit.Text = '' then
Var2Edit.Text := s;
Varlist.Items.Delete(index);
UpdateBtnStates;
end;
end;
procedure TSignTestFrm.VarListSelectionChange(Sender: TObject; User: boolean);
begin
UpdateBtnStates;
end;
procedure TSignTestFrm.UpdateBtnStates;
begin
Var1In.Enabled := (VarList.ItemIndex > -1) and (Var1Edit.Text = '');
Var2In.Enabled := (VarList.ItemIndex > -1) and (Var2Edit.Text = '');
Var1Out.Enabled := (Var1Edit.Text <> '');
Var2Out.Enabled := (Var2Edit.Text <> '');
end;
end.