LazStats: Refactor tTestUnit.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7845 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-11-05 13:38:59 +00:00
parent ff2834b9fe
commit 7ea76148e5
4 changed files with 300 additions and 218 deletions

View File

@ -1,7 +1,7 @@
inherited TtestForm: TTtestForm inherited TtestForm: TTtestForm
Left = 947 Left = 740
Height = 546 Height = 546
Top = 176 Top = 175
Width = 889 Width = 889
HelpType = htKeyword HelpType = htKeyword
HelpKeyword = 'html/tTests.htm' HelpKeyword = 'html/tTests.htm'
@ -40,7 +40,7 @@ inherited TtestForm: TTtestForm
end end
object Label1: TLabel[5] object Label1: TLabel[5]
AnchorSideLeft.Control = ParamsPanel AnchorSideLeft.Control = ParamsPanel
AnchorSideTop.Control = CInterval AnchorSideTop.Control = CIntervalEdit
AnchorSideTop.Side = asrCenter AnchorSideTop.Side = asrCenter
Left = 0 Left = 0
Height = 15 Height = 15
@ -49,7 +49,7 @@ inherited TtestForm: TTtestForm
Caption = 'Percent Confidence Interval:' Caption = 'Percent Confidence Interval:'
ParentColor = False ParentColor = False
end end
object CInterval: TEdit[6] object CIntervalEdit: TEdit[6]
AnchorSideLeft.Control = Label1 AnchorSideLeft.Control = Label1
AnchorSideLeft.Side = asrBottom AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = TailCombo AnchorSideTop.Control = TailCombo
@ -76,12 +76,12 @@ inherited TtestForm: TTtestForm
Height = 335 Height = 335
Top = 154 Top = 154
Width = 368 Width = 368
PageIndex = 0 PageIndex = 1
Anchors = [akTop, akLeft, akRight, akBottom] Anchors = [akTop, akLeft, akRight, akBottom]
TabOrder = 4 TabOrder = 4
object Page1: TPage object Page1: TPage
object Mean1Label: TLabel object Mean1Label: TLabel
AnchorSideLeft.Control = Mean1 AnchorSideLeft.Control = Mean1Edit
AnchorSideLeft.Side = asrCenter AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = Page1 AnchorSideTop.Control = Page1
Left = 83 Left = 83
@ -93,7 +93,7 @@ inherited TtestForm: TTtestForm
ParentColor = False ParentColor = False
end end
object Mean2Label: TLabel object Mean2Label: TLabel
AnchorSideTop.Control = Mean1 AnchorSideTop.Control = Mean1Edit
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Mean1Label AnchorSideRight.Control = Mean1Label
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
@ -107,7 +107,7 @@ inherited TtestForm: TTtestForm
ParentColor = False ParentColor = False
end end
object SD1Label: TLabel object SD1Label: TLabel
AnchorSideLeft.Control = SD1 AnchorSideLeft.Control = SD1Edit
AnchorSideLeft.Side = asrCenter AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = Mean1Label AnchorSideTop.Control = Mean1Label
Left = 157 Left = 157
@ -119,7 +119,7 @@ inherited TtestForm: TTtestForm
ParentColor = False ParentColor = False
end end
object SD2Label: TLabel object SD2Label: TLabel
AnchorSideLeft.Control = SD2 AnchorSideLeft.Control = SD2Edit
AnchorSideLeft.Side = asrCenter AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = Mean2Label AnchorSideTop.Control = Mean2Label
Left = 157 Left = 157
@ -131,7 +131,7 @@ inherited TtestForm: TTtestForm
ParentColor = False ParentColor = False
end end
object SampSize1Label: TLabel object SampSize1Label: TLabel
AnchorSideLeft.Control = N1 AnchorSideLeft.Control = N1Edit
AnchorSideLeft.Side = asrCenter AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = Mean1Label AnchorSideTop.Control = Mean1Label
Left = 231 Left = 231
@ -143,7 +143,7 @@ inherited TtestForm: TTtestForm
ParentColor = False ParentColor = False
end end
object SampSize2Label: TLabel object SampSize2Label: TLabel
AnchorSideLeft.Control = N2 AnchorSideLeft.Control = N2Edit
AnchorSideLeft.Side = asrCenter AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = Mean2Label AnchorSideTop.Control = Mean2Label
Left = 231 Left = 231
@ -155,9 +155,9 @@ inherited TtestForm: TTtestForm
ParentColor = False ParentColor = False
end end
object Cor12Label: TLabel object Cor12Label: TLabel
AnchorSideLeft.Control = Cor12 AnchorSideLeft.Control = Cor12Edit
AnchorSideLeft.Side = asrCenter AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = SD2 AnchorSideTop.Control = SD2Edit
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
Left = 111 Left = 111
Height = 15 Height = 15
@ -168,11 +168,11 @@ inherited TtestForm: TTtestForm
Caption = 'Correlation Between Scores:' Caption = 'Correlation Between Scores:'
ParentColor = False ParentColor = False
end end
object Mean1: TEdit object Mean1Edit: TEdit
AnchorSideLeft.Side = asrBottom AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = Mean1Label AnchorSideTop.Control = Mean1Label
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = SD1 AnchorSideRight.Control = SD1Edit
Left = 77 Left = 77
Height = 23 Height = 23
Top = 49 Top = 49
@ -183,13 +183,13 @@ inherited TtestForm: TTtestForm
BorderSpacing.Top = 2 BorderSpacing.Top = 2
BorderSpacing.Right = 32 BorderSpacing.Right = 32
TabOrder = 0 TabOrder = 0
Text = 'Mean1' Text = 'Mean1Edit'
end end
object Mean2: TEdit object Mean2Edit: TEdit
AnchorSideLeft.Control = Mean1 AnchorSideLeft.Control = Mean1Edit
AnchorSideTop.Control = Mean2Label AnchorSideTop.Control = Mean2Label
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Mean1 AnchorSideRight.Control = Mean1Edit
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 77 Left = 77
Height = 23 Height = 23
@ -199,12 +199,12 @@ inherited TtestForm: TTtestForm
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
BorderSpacing.Top = 2 BorderSpacing.Top = 2
TabOrder = 1 TabOrder = 1
Text = 'Mean2' Text = 'Mean2Edit'
end end
object SD1: TEdit object SD1Edit: TEdit
AnchorSideLeft.Control = Page1 AnchorSideLeft.Control = Page1
AnchorSideLeft.Side = asrCenter AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = Mean1 AnchorSideTop.Control = Mean1Edit
Left = 159 Left = 159
Height = 23 Height = 23
Top = 49 Top = 49
@ -212,12 +212,12 @@ inherited TtestForm: TTtestForm
Alignment = taRightJustify Alignment = taRightJustify
BorderSpacing.Left = 6 BorderSpacing.Left = 6
TabOrder = 2 TabOrder = 2
Text = 'SD1' Text = 'SD1Edit'
end end
object SD2: TEdit object SD2Edit: TEdit
AnchorSideLeft.Control = SD1 AnchorSideLeft.Control = SD1Edit
AnchorSideTop.Control = Mean2 AnchorSideTop.Control = Mean2Edit
AnchorSideRight.Control = SD1 AnchorSideRight.Control = SD1Edit
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 159 Left = 159
Height = 23 Height = 23
@ -226,12 +226,12 @@ inherited TtestForm: TTtestForm
Alignment = taRightJustify Alignment = taRightJustify
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
TabOrder = 3 TabOrder = 3
Text = 'SD2' Text = 'SD2Edit'
end end
object N1: TEdit object N1Edit: TEdit
AnchorSideLeft.Control = SD1 AnchorSideLeft.Control = SD1Edit
AnchorSideLeft.Side = asrBottom AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = Mean1 AnchorSideTop.Control = Mean1Edit
Left = 241 Left = 241
Height = 23 Height = 23
Top = 49 Top = 49
@ -239,12 +239,12 @@ inherited TtestForm: TTtestForm
Alignment = taRightJustify Alignment = taRightJustify
BorderSpacing.Left = 32 BorderSpacing.Left = 32
TabOrder = 4 TabOrder = 4
Text = 'N1' Text = 'N1Edit'
end end
object N2: TEdit object N2Edit: TEdit
AnchorSideLeft.Control = N1 AnchorSideLeft.Control = N1Edit
AnchorSideTop.Control = Mean2 AnchorSideTop.Control = Mean2Edit
AnchorSideRight.Control = N1 AnchorSideRight.Control = N1Edit
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 241 Left = 241
Height = 23 Height = 23
@ -253,10 +253,10 @@ inherited TtestForm: TTtestForm
Alignment = taRightJustify Alignment = taRightJustify
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
TabOrder = 5 TabOrder = 5
Text = 'N2' Text = 'N2Edit'
end end
object Cor12: TEdit object Cor12Edit: TEdit
AnchorSideLeft.Control = SD1 AnchorSideLeft.Control = SD1Edit
AnchorSideLeft.Side = asrCenter AnchorSideLeft.Side = asrCenter
AnchorSideTop.Control = Cor12Label AnchorSideTop.Control = Cor12Label
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
@ -267,7 +267,7 @@ inherited TtestForm: TTtestForm
Alignment = taRightJustify Alignment = taRightJustify
BorderSpacing.Top = 2 BorderSpacing.Top = 2
TabOrder = 6 TabOrder = 6
Text = 'Cor12' Text = 'Cor12Edit'
end end
end end
object Page2: TPage object Page2: TPage
@ -277,8 +277,8 @@ inherited TtestForm: TTtestForm
Left = 0 Left = 0
Height = 15 Height = 15
Top = 0 Top = 0
Width = 83 Width = 97
Caption = 'Select Variables:' Caption = 'Available Variables'
ParentColor = False ParentColor = False
end end
object VarList: TListBox object VarList: TListBox
@ -307,12 +307,12 @@ inherited TtestForm: TTtestForm
Left = 203 Left = 203
Height = 15 Height = 15
Top = 25 Top = 25
Width = 62 Width = 59
Alignment = taRightJustify Alignment = taRightJustify
Anchors = [akLeft, akBottom] Anchors = [akLeft, akBottom]
BorderSpacing.Right = 8 BorderSpacing.Right = 8
BorderSpacing.Bottom = 2 BorderSpacing.Bottom = 2
Caption = '1st Variable:' Caption = '1st Variable'
ParentColor = False ParentColor = False
end end
object Var2Label: TLabel object Var2Label: TLabel
@ -321,11 +321,11 @@ inherited TtestForm: TTtestForm
Left = 203 Left = 203
Height = 15 Height = 15
Top = 101 Top = 101
Width = 67 Width = 64
Alignment = taRightJustify Alignment = taRightJustify
Anchors = [akLeft, akBottom] Anchors = [akLeft, akBottom]
BorderSpacing.Right = 8 BorderSpacing.Right = 8
Caption = '2nd Variable:' Caption = '2nd Variable'
ParentColor = False ParentColor = False
end end
object GrpLabel: TLabel object GrpLabel: TLabel
@ -335,12 +335,12 @@ inherited TtestForm: TTtestForm
Left = 203 Left = 203
Height = 15 Height = 15
Top = 177 Top = 177
Width = 67 Width = 77
Alignment = taRightJustify Alignment = taRightJustify
Anchors = [akLeft, akBottom] Anchors = [akLeft, akBottom]
BorderSpacing.Right = 8 BorderSpacing.Right = 8
BorderSpacing.Bottom = 2 BorderSpacing.Bottom = 2
Caption = 'Group Code:' Caption = 'Group Variable'
ParentColor = False ParentColor = False
end end
object Bevel5: TBevel object Bevel5: TBevel
@ -651,7 +651,7 @@ inherited TtestForm: TTtestForm
end end
object Bevel3: TBevel[10] object Bevel3: TBevel[10]
AnchorSideLeft.Control = ParamsPanel AnchorSideLeft.Control = ParamsPanel
AnchorSideTop.Control = CInterval AnchorSideTop.Control = CIntervalEdit
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = ParamsPanel AnchorSideRight.Control = ParamsPanel
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom

View File

@ -31,8 +31,8 @@ type
Page1: TPage; Page1: TPage;
Page2: TPage; Page2: TPage;
Cor12Label: TLabel; Cor12Label: TLabel;
Cor12: TEdit; Cor12Edit: TEdit;
CInterval: TEdit; CIntervalEdit: TEdit;
GrpEdit: TEdit; GrpEdit: TEdit;
Label1: TLabel; Label1: TLabel;
Var1In: TBitBtn; Var1In: TBitBtn;
@ -44,16 +44,16 @@ type
Var2Label: TLabel; Var2Label: TLabel;
VarList: TListBox; VarList: TListBox;
SelVarLabel: TLabel; SelVarLabel: TLabel;
N2: TEdit; N2Edit: TEdit;
N1: TEdit; N1Edit: TEdit;
SampSize2Label: TLabel; SampSize2Label: TLabel;
SampSize1Label: TLabel; SampSize1Label: TLabel;
SD2: TEdit; SD2Edit: TEdit;
SD1: TEdit; SD1Edit: TEdit;
SD2Label: TLabel; SD2Label: TLabel;
SD1Label: TLabel; SD1Label: TLabel;
Mean2: TEdit; Mean2Edit: TEdit;
Mean1: TEdit; Mean1Edit: TEdit;
Mean2Label: TLabel; Mean2Label: TLabel;
Mean1Label: TLabel; Mean1Label: TLabel;
DataEntryGroup: TRadioGroup; DataEntryGroup: TRadioGroup;
@ -76,6 +76,12 @@ type
independent: boolean; independent: boolean;
griddata: boolean; griddata: boolean;
function Eval_DependentGridData(out AMean1, AMean2, AVariance1, AVariance2,
AStdDev1, AStdDev2, ACovar12, r12: Double; out ANumCases1, ANumCases2: Integer): Boolean;
function Eval_IndependentGridData(out AMean1, AMean2, AVariance1, AVariance2,
AStdDev1, AStdDev2: Double; out ANumCases1, ANumCases2: Integer;
out ALabel1Str, ALabel2Str: String): Boolean;
protected protected
procedure AdjustConstraints; override; procedure AdjustConstraints; override;
procedure Compute; override; procedure Compute; override;
@ -97,7 +103,7 @@ implementation
uses uses
Math, Math,
MathUnit, GridProcs; Utils, MathUnit, MatrixUnit, GridProcs;
{ TTtestForm } { TTtestForm }
@ -105,7 +111,7 @@ uses
constructor TTtestForm.Create(AOwner: TComponent); constructor TTtestForm.Create(AOwner: TComponent);
begin begin
inherited; inherited;
CInterval.Text := FormatFloat('0.0', DEFAULT_CONFIDENCE_LEVEL_PERCENT); CIntervalEdit.Text := FormatFloat('0.0', DEFAULT_CONFIDENCE_LEVEL_PERCENT);
end; end;
@ -119,7 +125,7 @@ begin
); );
ParamsPanel.Constraints.MinHeight := DataEntryGroup.Height + ParamsPanel.Constraints.MinHeight := DataEntryGroup.Height +
TailCombo.BorderSpacing.Top + TailCombo.Height + TailCombo.BorderSpacing.Top + TailCombo.Height +
CInterval.BorderSpacing.Top + CInterval.Height + CInterval.BorderSpacing.Bottom + CIntervalEdit.BorderSpacing.Top + CIntervalEdit.Height + CIntervalEdit.BorderSpacing.Bottom +
Bevel3.Height + Bevel3.BorderSpacing.Bottom + Bevel3.Height + Bevel3.BorderSpacing.Bottom +
GrpIn.Top + GroupCodeGroup.Height + GrpIn.Top + GroupCodeGroup.Height +
ButtonBevel.Height + CloseBtn.BorderSpacing.Top + CloseBtn.Height; ButtonBevel.Height + CloseBtn.BorderSpacing.Top + CloseBtn.Height;
@ -128,154 +134,58 @@ end;
procedure TTtestForm.Compute; procedure TTtestForm.Compute;
var var
M1, M2, Dif, stddev1, stddev2, r12, stderr1, stderr2: double; mean1, mean2, Dif, stddev1, stddev2, r12, stderr1, stderr2: double;
tequal, tunequal, cov12, lowci, hici, F, Fp, df1, df2: double; tequal, tunequal, cov12, lowci, hici, F, Fp, df1, df2: double;
tprobability, value1, value2: double; tprobability, value1, value2: double;
variance1, variance2, pooled, sedif, df, ConfInt, tconfint: double; variance1, variance2, pooled, sedif, df, ConfInt, tconfint: double;
i, nCases1, nCases2: integer; i, nCases1, nCases2: integer;
group, min, max: integer; group, min, max: integer;
minf, maxf: Double;
ColNoSelected: IntDyneVec = nil; ColNoSelected: IntDyneVec = nil;
label1Str, label2Str: string; label1Str, label2Str: string;
lReport: TStrings; lReport: TStrings;
begin begin
SetLength(ColNoSelected,NoVariables); ConfInt := (100.0 - StrToFloat(CIntervalEdit.Text)) / 2.0 ;
ncases1 := 0;
ncases2 := 0;
variance1 := 0.0;
variance2 := 0.0;
M1 := 0.0;
M2 := 0.0;
Dif := 0.0;
r12 := 0.0;
stddev1 := 0.0;
stddev2 := 0.0;
ConfInt := (100.0 - StrToFloat(CInterval.Text)) / 2.0 ;
ConfInt := (100.0 - ConfInt) / 100.0; // one tail ConfInt := (100.0 - ConfInt) / 100.0; // one tail
if independent then
Var2Edit.Text := GrpEdit.Text;
// data read from grid
if griddata then if griddata then
begin begin
SetLength(ColNoSelected, 2); // Read and analyze data from grid
ColNoSelected[0] := GetVariableIndex(OS3MainFrm.DataGrid, Var1Edit.Text);
ColNoSelected[1] := GetVariableIndex(OS3MainFrm.DataGrid, Var2Edit.Text);
ncases1 := 0;
ncases2 := 0;
M1 := 0.0;
M2 := 0.0;
variance1 := 0.0;
variance2 := 0.0;
r12 := 0.0;
if not independent then // correlated data
begin
for i := 1 to NoCases do
begin
if not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected) then continue;
ncases1 := ncases1 + 1;
value1 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[0], i]));
value2 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[1], i]));
M1 := M1 + value1;
M2 := M2 + value2;
variance1 := variance1 + value1 * value1;
variance2 := variance2 + value2 * value2;
r12 := r12 + value1 * value2;
end;
ncases2 := ncases1;
variance1 := variance1 - (M1 * M1 / ncases1);
variance1 := variance1 / (ncases1 - 1);
stddev1 := sqrt(variance1);
variance2 := variance2 - (M2 * M2 / ncases2);
variance2 := variance2 / (ncases2 - 1);
stddev2 := sqrt(variance2);
r12 := r12 - (M1 * M2 / ncases1);
r12 := r12 / (ncases1 - 1);
cov12 := r12;
r12 := r12 / (stddev1 * stddev2);
M1 := M1 / ncases1;
M2 := M2 / ncases2;
Dif := M1 - M2;
end; //if not independent
if independent then if independent then
begin begin
if GroupCodeChk.Checked then if not Eval_IndependentGridData(
begin mean1, mean2, variance1, variance2, stddev1, stddev2,
min := StrToInt(Grp1CodeEdit.Text); nCases1, nCases2, Label1Str, Label2Str)
max := StrToInt(Grp2CodeEdit.Text); then
exit;
end else end else
begin begin
min := MaxInt; if not Eval_DependentGridData(
max := min; mean1, mean2, variance1, variance2, stddev1, stddev2,
cov12, r12, nCases1, nCases2)
then
exit;
end; end;
end else
for i := 1 to NoCases do
begin begin
if not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected) then continue; // Read data from form
group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[1], i]))); mean1 := StrToFloat(mean1Edit.Text);
if not GroupCodeChk.Checked then mean2 := StrToFloat(mean2Edit.Text);
begin stddev1 := StrToFloat(SD1Edit.Text);
if group < min then min := group; stddev2 := StrToFloat(SD2Edit.Text);
if group > max then max := group; ncases1 := round(StrToFloat(N1Edit.Text));
end; ncases2 := round(StrToFloat(N2Edit.Text));
end;
for i := 1 to NoCases do
begin
if not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected) then continue;
value1 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[0], i]));
value2 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNoSelected[1], i]));
group := round(value2);
if group = min then
begin
M1 := M1 + value1;
variance1 := variance1 + (value1 * value1);
ncases1 := ncases1 + 1;
end else if group = max then
begin
M2 := M2 + value1;
variance2 := variance2 + (value1 * value1);
ncases2 := Ncases2 + 1;
end;
end; // next case
variance1 := variance1 - ((M1 * M1) / ncases1);
variance1 := variance1 / (ncases1 - 1);
stddev1 := sqrt(variance1);
variance2 := variance2 - ((M2 * M2) / ncases2);
variance2 := variance2 / (ncases2 - 1);
stddev2 := sqrt(variance2);
M1 := M1 / ncases1;
M2 := M2 / ncases2;
Dif := M1 - M2;
Label1Str := format('Group %d',[min]);
Label2Str := format('Group %d',[max]);
end; // if independent data
end; // if reading grid data
if not griddata then // data read from form
begin
M1 := StrToFloat(Mean1.Text);
M2 := StrToFloat(Mean2.Text);
stddev1 := StrToFloat(SD1.Text);
stddev2 := StrToFloat(SD2.Text);
ncases1 := round(StrToFloat(N1.Text));
ncases2 := round(StrToFloat(N2.Text));
variance1 := stddev1 * stddev1; variance1 := stddev1 * stddev1;
variance2 := stddev2 * stddev2; variance2 := stddev2 * stddev2;
Label1Str := 'Group 1'; Label1Str := 'Group 1';
Label2Str := 'Group 2'; Label2Str := 'Group 2';
Dif := M1 - M2;
if not independent then if not independent then
begin begin
r12 := StrToFloat(Cor12.Text); r12 := StrToFloat(Cor12Edit.Text);
cov12 := r12 * stddev1 * stddev2; cov12 := r12 * stddev1 * stddev2;
end; end;
end; end;
dif := mean1 - mean2;
// Initialize output form // Initialize output form
lReport := TStringList.Create; lReport := TStringList.Create;
@ -289,8 +199,8 @@ begin
stderr1 := sqrt(variance1 / ncases1); stderr1 := sqrt(variance1 / ncases1);
Stderr2 := sqrt(variance2 / ncases2); Stderr2 := sqrt(variance2 / ncases2);
lReport.Add('Variable Mean Variance Std.Dev. S.E.Mean N'); lReport.Add('Variable Mean Variance Std.Dev. S.E.Mean N');
lReport.Add('%-10s%8.2f %8.2f %8.2f %8.2f %d', [Label1Str, M1, variance1, stddev1, stderr1, ncases1]); lReport.Add('%-10s%8.2f %8.2f %8.2f %8.2f %d', [Label1Str, mean1, variance1, stddev1, stderr1, ncases1]);
lReport.Add('%-10s%8.2f %8.2f %8.2f %8.2f %d', [Label2Str, M2, variance2, stddev2, stderr2, ncases2]); lReport.Add('%-10s%8.2f %8.2f %8.2f %8.2f %d', [Label2Str, mean2, variance2, stddev2, stderr2, ncases2]);
lReport.Add(''); lReport.Add('');
pooled := ((ncases1-1) * variance1) + ((ncases2-1) * variance2); pooled := ((ncases1-1) * variance1) + ((ncases2-1) * variance2);
@ -349,8 +259,8 @@ begin
stderr1 := sqrt(variance1 / ncases1); stderr1 := sqrt(variance1 / ncases1);
Stderr2 := sqrt(variance2 / ncases2); Stderr2 := sqrt(variance2 / ncases2);
lReport.Add('Variable Mean Variance Std.Dev. S.E.Mean N'); lReport.Add('Variable Mean Variance Std.Dev. S.E.Mean N');
lReport.Add('%-10s%8.2f %8.2f %8.2f %8.2f %d', [Label1Str, M1, variance1, stddev1, stderr1, ncases1]); lReport.Add('%-10s%8.2f %8.2f %8.2f %8.2f %d', [Label1Str, mean1, variance1, stddev1, stderr1, ncases1]);
lReport.Add('%-10s%8.2f %8.2f %8.2f %8.2f %d', [Label2Str,M2, variance2, stddev2, stderr2, ncases2]); lReport.Add('%-10s%8.2f %8.2f %8.2f %8.2f %d', [Label2Str, mean2, variance2, stddev2, stderr2, ncases2]);
lReport.Add(''); lReport.Add('');
sedif := variance1 + variance2 - (2.0 * cov12); sedif := variance1 + variance2 - (2.0 * cov12);
sedif := sqrt(sedif / ncases1); sedif := sqrt(sedif / ncases1);
@ -399,6 +309,9 @@ begin
Var2Edit.Visible := false; Var2Edit.Visible := false;
end; end;
GroupCodeChk.Visible := independent;
GroupCodeGroup.Visible := independent;
Var2Label.Visible := Var2Edit.Visible; Var2Label.Visible := Var2Edit.Visible;
Var2In.Visible := Var2Edit.Visible; Var2In.Visible := Var2Edit.Visible;
Var2Out.Visible := Var2Edit.Visible; Var2Out.Visible := Var2Edit.Visible;
@ -427,11 +340,109 @@ begin
Var2In.Visible := not independent; Var2In.Visible := not independent;
Var2Out.Visible := not independent; Var2Out.Visible := not independent;
Cor12.Visible := not independent; Cor12Edit.Visible := not independent;
Cor12Label.Visible := not independent; Cor12Label.Visible := not independent;
end; end;
function TtTestForm.Eval_DependentGridData(out AMean1, AMean2,
AVariance1, AVariance2, AStdDev1, AStdDev2, ACovar12, r12: Double;
out ANumCases1, ANumCases2: Integer): Boolean;
var
colNoSelected: IntDyneVec = nil;
values1: DblDyneVec = nil;
values2: DblDyneVec = nil;
begin
SetLength(colNoSelected, 2);
colNoSelected[0] := GetVariableIndex(OS3MainFrm.DataGrid, Var1Edit.Text);
colNoSelected[1] := GetVariableIndex(OS3MainFrm.DataGrid, Var2Edit.Text);
values1 := CollectVecValues(OS3MainFrm.DataGrid, colNoSelected[0], colNoSelected);
values2 := CollectVecValues(OS3MainFrm.DataGrid, colNoSelected[1], colNoSelected);
ANumCases1 := Length(values1);
ANumCases2 := Length(values2);
if ANumCases1 <> ANumCases2 then
begin
ErrorMsg('Both variables must have the same count of cases.');
Result := false;
exit;
end;
if ANumCases1 < 2 then
begin
ErrorMsg('There must be at least two cases.');
Result := false;
exit;
end;
VecMeanVarStdDev(values1, AMean1, AVariance1, AStdDev1);
VecMeanVarStdDev(values2, AMean2, AVariance2, AStdDev2);
ACovar12 := (values1 - AMean1) * (values2 - AMean2) / (ANumCases1-1);
r12 := ACovar12 / (AStdDev1 * AStdDev2);
Result := true;
end;
function TtTestForm.Eval_IndependentGridData(out AMean1, AMean2,
AVariance1, AVariance2, AStdDev1, AStdDev2: Double;
out ANumCases1, ANumCases2: Integer; out ALabel1Str, ALabel2Str: String): Boolean;
var
colNoSelected: IntDyneVec = nil;
values1: DblDyneVec = nil;
values2: DblDyneVec = nil;
grp1, grp2: Integer;
minf, maxf: Double;
begin
SetLength(colNoSelected, 2);
colNoSelected[0] := GetVariableIndex(OS3MainFrm.DataGrid, Var1Edit.Text);
colNoSelected[1] := GetVariableIndex(OS3MainFrm.DataGrid, GrpEdit.Text);
if GroupCodeChk.Checked then
begin
grp1 := StrToInt(Grp1CodeEdit.Text);
grp2 := StrToInt(Grp2CodeEdit.Text);
end else
begin
GetMinMax(OS3MainFrm.DataGrid, colNoSelected[1], colNoSelected, minf, maxf);
grp1 := round(minf);
grp2 := round(maxf);
end;
// Values in group with code given by grp1
values1 := CollectFilteredVecValues(OS3MainFrm.DataGrid, colNoSelected[0], colNoSelected[1], grp1, colNoSelected);
// Values in group with code given by grp2
values2 := CollectFilteredVecValues(OS3MainFrm.DataGrid, colNoSelected[0], colNoSelected[1], grp2, colNoSelected);
ANumCases1 := Length(values1);
ANumCases2 := Length(values2);
if ANumCases1 <> ANumCases2 then
begin
ErrorMsg('Both variables must have the same count of cases.');
Result := false;
exit;
end;
if ANumCases1 < 2 then begin
ErrorMsg('There must be at least 2 cases.');
Result := false;
exit;
end;
VecMeanVarStdDev(values1, AMean1, AVariance1, AStdDev1);
VecMeanVarStdDev(values2, AMean2, AVariance2, AStdDev2);
ALabel1Str := format('Group %d', [grp1]);
ALabel2Str := format('Group %d', [grp2]);
Result := true;
end;
procedure TTtestForm.GroupCodeChkChange(Sender: TObject); procedure TTtestForm.GroupCodeChkChange(Sender: TObject);
begin begin
Grp1CodeEdit.Enabled := GroupCodeChk.Checked; Grp1CodeEdit.Enabled := GroupCodeChk.Checked;
@ -482,13 +493,13 @@ begin
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
Var1Edit.Clear; Var1Edit.Clear;
Var2Edit.Clear; Var2Edit.Clear;
Mean1.Clear; Mean1Edit.Clear;
Mean2.Clear; Mean2Edit.Clear;
SD1.Clear; SD1Edit.Clear;
SD2.Clear; SD2Edit.Clear;
N1.Clear; N1Edit.Clear;
N2.Clear; N2Edit.Clear;
Cor12.Clear; Cor12Edit.Clear;
GroupCodeChk.Checked := false; GroupCodeChk.Checked := false;
GrpEdit.Clear; GrpEdit.Clear;
Grp1CodeEdit.Clear; Grp1CodeEdit.Clear;
@ -524,39 +535,39 @@ begin
AMsg := ''; AMsg := '';
if Notebook.PageIndex = 0 then if Notebook.PageIndex = 0 then
begin begin
if (Mean1.Text = '') or not TryStrToFloat(Mean1.Text, x) then if (Mean1Edit.Text = '') or not TryStrToFloat(Mean1Edit.Text, x) then
begin begin
AControl := Mean1; AControl := Mean1Edit;
AMsg := 'Invalid input for the mean of sample 1'; AMsg := 'Invalid input for the mean of sample 1';
exit; exit;
end; end;
if (SD1.Text = '') or not TryStrToFloat(SD1.Text, x) or (x <= 0) then if (SD1Edit.Text = '') or not TryStrToFloat(SD1Edit.Text, x) or (x <= 0) then
begin begin
AControl := SD1; AControl := SD1Edit;
AMsg := 'Invald input for the standard deviation of sample 1'; AMsg := 'Invald input for the standard deviation of sample 1';
exit; exit;
end; end;
if (N1.Text = '') or not TryStrToInt(N1.Text, n) or (n <= 0) then if (N1Edit.Text = '') or not TryStrToInt(N1Edit.Text, n) or (n <= 0) then
begin begin
AControl := N1; AControl := N1Edit;
AMsg := 'Invald input for the size of sample 1'; AMsg := 'Invald input for the size of sample 1';
exit; exit;
end; end;
if (Mean2.Text = '') or not TryStrToFloat(Mean2.Text, x) then if (Mean2Edit.Text = '') or not TryStrToFloat(Mean2Edit.Text, x) then
begin begin
AControl := Mean2; AControl := Mean2Edit;
AMsg := 'Invalid input for the mean of sample 2'; AMsg := 'Invalid input for the mean of sample 2';
exit; exit;
end; end;
if (SD2.Text = '') or not TryStrToFloat(SD2.Text, x) or (x <= 0) then if (SD2Edit.Text = '') or not TryStrToFloat(SD2Edit.Text, x) or (x <= 0) then
begin begin
AControl := SD2; AControl := SD2Edit;
AMsg := 'Invald input for the standard deviation of sample 2'; AMsg := 'Invald input for the standard deviation of sample 2';
exit; exit;
end; end;
if (N2.Text = '') or not TryStrToInt(N2.Text, n) or (n <= 0) then if (N2Edit.Text = '') or not TryStrToInt(N2Edit.Text, n) or (n <= 0) then
begin begin
AControl := N2; AControl := N2Edit;
AMsg := 'Invald input for the size of sample 2'; AMsg := 'Invald input for the size of sample 2';
exit; exit;
end; end;
@ -581,19 +592,24 @@ begin
AMsg := 'Group variable not specified.'; AMsg := 'Group variable not specified.';
exit; exit;
end; end;
if Grp1CodeEdit.Visible and ((Grp1CodeEdit.Text = '') or not TryStrToInt(Grp1CodeEdit.Text, n))then if GroupCodeChk.Checked then
begin
if Grp1CodeEdit.Visible and
((Grp1CodeEdit.Text = '') or not TryStrToInt(Grp1CodeEdit.Text, n)) then
begin begin
AControl := Grp1CodeEdit; AControl := Grp1CodeEdit;
AMsg := 'Code for group 1 missing.'; AMsg := 'Code for group 1 missing.';
exit; exit;
end; end;
if Grp2CodeEdit.Visible and ((Grp2CodeEdit.Text = '') or not TryStrToInt(Grp2CodeEdit.Text, n))then if Grp2CodeEdit.Visible and
((Grp2CodeEdit.Text = '') or not TryStrToInt(Grp2CodeEdit.Text, n))then
begin begin
AControl := Grp2CodeEdit; AControl := Grp2CodeEdit;
AMsg := 'Code for group 2 missing.'; AMsg := 'Code for group 2 missing.';
exit; exit;
end; end;
end; end;
end;
Result := true; Result := true;
end; end;

View File

@ -11,6 +11,9 @@ uses
function CollectVecValues(AGrid: TStringGrid; AColIndex: Integer; function CollectVecValues(AGrid: TStringGrid; AColIndex: Integer;
AColCheck: IntDyneVec = nil): DblDyneVec; AColCheck: IntDyneVec = nil): DblDyneVec;
function CollectFilteredVecValues(AGrid: TStringGrid; AColIndex, AFilterColIndex: Integer;
AcceptValue: Double; AColCheck: IntDyneVec = nil): DblDyneVec;
function CollectMatValues(AGrid: TStringGrid; AColIndices: IntDyneVec): DblDyneMat; function CollectMatValues(AGrid: TStringGrid; AColIndices: IntDyneVec): DblDyneMat;
procedure GetMinMax(AGrid: TStringGrid; AColIndex: Integer; procedure GetMinMax(AGrid: TStringGrid; AColIndex: Integer;
@ -73,6 +76,43 @@ begin
end; end;
{ Extracts the grid values from the column with index AColIndex, but only those
for which the value in the same row, but column AFilterCalIndex matches the
AcceptValue }
function CollectFilteredVecValues(AGrid: TStringGrid; AColIndex, AFilterColIndex: Integer;
AcceptValue: Double; AColCheck: IntDyneVec = nil): DblDyneVec;
var
row, n: Integer;
val1, val2: Double;
begin
Result := nil;
SetLength(Result, AGrid.RowCount);
n := 0;
for row := 1 to AGrid.RowCount-1 do
begin
if Length(AColCheck) = 0 then
begin
if not ValidValue(AGrid, row, AColIndex) then continue;
if not ValidValue(AGrid, row, AFilterColIndex) then continue;
end else
if not GoodRecord(AGrid, row, AColCheck) then continue;
if not TryStrToFloat(trim(AGrid.Cells[AColIndex, row]), val1) then
raise ELazStats.CreateFmt('Non-numeric string "%s" in column %d, row %d',
[AGrid.Cells[AColIndex, row]]);
if not TryStrToFloat(trim(AGrid.Cells[AFilterColIndex, row]), val2) then
raise ELazStats.CreateFmt('Non-numeric string "%s" in column %d, row %d',
[AGrid.Cells[AFilterColIndex, row]]);
if val2 = AcceptValue then
begin
Result[n] := val1;
inc(n);
end;
end;
SetLength(Result, n);
end;
{ Extracts the grid values from the columns with indices given by AColIndices { Extracts the grid values from the columns with indices given by AColIndices
and puts them into the columns of the result matrix. and puts them into the columns of the result matrix.
This means: The result matrix contains the variables as columns and the This means: The result matrix contains the variables as columns and the

View File

@ -21,7 +21,9 @@ type
// Vectors // Vectors
operator + (A, B: TDblVector): TDblVector; operator + (A, B: TDblVector): TDblVector;
operator + (A: TDblVector; b: double): TDblVector;
operator - (A, B: TDblVector): TDblVector; operator - (A, B: TDblVector): TDblVector;
operator - (A: TDblVector; b: double): TDblVector;
operator * (A, B: TDblVector): Double; operator * (A, B: TDblVector): Double;
operator * (A: TDblVector; b: Double): TDblVector; operator * (A: TDblVector; b: Double): TDblVector;
operator * (a: Double; B: TDblVector): TDblVector; operator * (a: Double; B: TDblVector): TDblVector;
@ -129,6 +131,18 @@ begin
end; end;
operator + (A: TDblVector; b: double): TDblVector;
var
i, n: Integer;
begin
Result := nil;
n := Length(A);
Setlength(Result, n);
for i := 0 to n-1 do
Result[i] := A[i] + b;
end;
operator - (A, B: TDblVector): TDblVector; operator - (A, B: TDblVector): TDblVector;
var var
i, n: Integer; i, n: Integer;
@ -141,6 +155,18 @@ begin
end; end;
operator - (A: TDblVector; b: double): TDblVector;
var
i, n: Integer;
begin
Result := nil;
n := Length(A);
Setlength(Result, n);
for i := 0 to n-1 do
Result[i] := A[i] - b;
end;
// Vector dot product // Vector dot product
operator * (A, B: TDblVector): Double; operator * (A, B: TDblVector): Double;
var var