diff --git a/applications/lazstats/source/LazStats.lpi b/applications/lazstats/source/LazStats.lpi index f57439962..829217fc2 100644 --- a/applications/lazstats/source/LazStats.lpi +++ b/applications/lazstats/source/LazStats.lpi @@ -721,7 +721,7 @@ - + diff --git a/applications/lazstats/source/forms/analysis/nonparametric/mannwhituunit.lfm b/applications/lazstats/source/forms/analysis/nonparametric/mannwhituunit.lfm index c39152ad6..c9ba2e186 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/mannwhituunit.lfm +++ b/applications/lazstats/source/forms/analysis/nonparametric/mannwhituunit.lfm @@ -1,249 +1,186 @@ -object MannWhitUFrm: TMannWhitUFrm +inherited MannWhitUForm: TMannWhitUForm Left = 540 - Height = 321 + Height = 400 Top = 256 - Width = 373 + Width = 654 HelpType = htKeyword HelpKeyword = 'html/Mann-WhitneyUTest.htm' - AutoSize = True Caption = 'Mann-Whitney U Test' - ClientHeight = 321 - ClientWidth = 373 - OnActivate = FormActivate - OnCreate = FormCreate - OnShow = FormShow - Position = poMainFormCenter - LCLVersion = '2.1.0.0' - object Label1: TLabel - AnchorSideLeft.Control = Owner - AnchorSideTop.Control = Owner - Left = 8 - Height = 15 - Top = 8 - Width = 97 - BorderSpacing.Left = 8 - BorderSpacing.Top = 8 - Caption = 'Variables Available' - ParentColor = False + ClientHeight = 400 + ClientWidth = 654 + inherited ParamsPanel: TPanel + Height = 384 + ClientHeight = 384 + inherited CloseBtn: TButton + Top = 359 + end + inherited ComputeBtn: TButton + Top = 359 + end + inherited ResetBtn: TButton + Top = 359 + end + inherited HelpBtn: TButton + Top = 359 + end + inherited ButtonBevel: TBevel + Top = 343 + end + object Label1: TLabel[5] + AnchorSideLeft.Control = ParamsPanel + AnchorSideTop.Control = ParamsPanel + Left = 0 + Height = 15 + Top = 0 + Width = 97 + Caption = 'Available Variables' + ParentColor = False + end + object Label2: TLabel[6] + AnchorSideLeft.Control = GrpEdit + AnchorSideBottom.Control = GrpEdit + Left = 164 + Height = 15 + Top = 21 + Width = 77 + Anchors = [akLeft, akBottom] + BorderSpacing.Right = 8 + BorderSpacing.Bottom = 2 + Caption = 'Group Variable' + ParentColor = False + end + object Label3: TLabel[7] + AnchorSideLeft.Control = DepEdit + AnchorSideBottom.Control = DepEdit + Left = 164 + Height = 15 + Top = 109 + Width = 102 + Anchors = [akLeft, akBottom] + BorderSpacing.Right = 8 + BorderSpacing.Bottom = 2 + Caption = 'Dependent Variable' + ParentColor = False + end + object VarList: TListBox[8] + AnchorSideLeft.Control = ParamsPanel + AnchorSideTop.Control = Label1 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = GrpIn + AnchorSideBottom.Control = ButtonBevel + Left = 0 + Height = 326 + Top = 17 + Width = 126 + Anchors = [akTop, akLeft, akRight, akBottom] + BorderSpacing.Top = 2 + BorderSpacing.Right = 6 + ItemHeight = 0 + OnDblClick = VarListDblClick + OnSelectionChange = VarListSelectionChange + TabOrder = 4 + end + object GrpIn: TBitBtn[9] + AnchorSideLeft.Control = ParamsPanel + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = VarList + Left = 132 + Height = 26 + Top = 17 + Width = 26 + Images = MainDataModule.ImageList + ImageIndex = 1 + OnClick = GrpInClick + Spacing = 0 + TabOrder = 5 + end + object GrpOut: TBitBtn[10] + AnchorSideLeft.Control = ParamsPanel + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = GrpIn + AnchorSideTop.Side = asrBottom + Left = 132 + Height = 26 + Top = 47 + Width = 26 + BorderSpacing.Top = 4 + Images = MainDataModule.ImageList + ImageIndex = 0 + OnClick = GrpOutClick + Spacing = 0 + TabOrder = 6 + end + object DepIn: TBitBtn[11] + AnchorSideLeft.Control = ParamsPanel + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = GrpOut + AnchorSideTop.Side = asrBottom + Left = 132 + Height = 26 + Top = 105 + Width = 26 + BorderSpacing.Top = 32 + Images = MainDataModule.ImageList + ImageIndex = 1 + OnClick = DepInClick + Spacing = 0 + TabOrder = 7 + end + object DepOut: TBitBtn[12] + AnchorSideLeft.Control = ParamsPanel + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = DepIn + AnchorSideTop.Side = asrBottom + Left = 132 + Height = 26 + Top = 135 + Width = 26 + BorderSpacing.Top = 4 + Images = MainDataModule.ImageList + ImageIndex = 0 + OnClick = DepOutClick + Spacing = 0 + TabOrder = 8 + end + object GrpEdit: TEdit[13] + AnchorSideLeft.Control = GrpIn + AnchorSideLeft.Side = asrBottom + AnchorSideRight.Control = ParamsPanel + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = GrpOut + AnchorSideBottom.Side = asrBottom + Left = 164 + Height = 23 + Top = 38 + Width = 127 + Anchors = [akLeft, akRight, akBottom] + BorderSpacing.Left = 6 + BorderSpacing.Bottom = 12 + ReadOnly = True + TabOrder = 9 + Text = 'GrpEdit' + end + object DepEdit: TEdit[14] + AnchorSideLeft.Control = DepIn + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = ParamsPanel + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = DepOut + AnchorSideBottom.Side = asrBottom + Left = 164 + Height = 23 + Top = 126 + Width = 127 + Anchors = [akLeft, akRight, akBottom] + BorderSpacing.Left = 6 + BorderSpacing.Bottom = 12 + ReadOnly = True + TabOrder = 10 + Text = 'DepEdit' + end end - object Label2: TLabel - AnchorSideLeft.Control = GrpEdit - AnchorSideBottom.Control = GrpEdit - Left = 245 - Height = 15 - Top = 33 - Width = 77 - Anchors = [akLeft, akBottom] - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 2 - Caption = 'Group Variable' - ParentColor = False - end - object Label3: TLabel - AnchorSideLeft.Control = DepEdit - AnchorSideBottom.Control = DepEdit - Left = 245 - Height = 15 - Top = 125 - Width = 102 - Anchors = [akLeft, akBottom] - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 2 - Caption = 'Dependent Variable' - ParentColor = False - end - object VarList: TListBox - AnchorSideLeft.Control = Owner - AnchorSideTop.Control = Label1 - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = GrpIn - AnchorSideBottom.Control = Bevel2 - Left = 8 - Height = 247 - Top = 25 - Width = 193 - Anchors = [akTop, akLeft, akRight, akBottom] - BorderSpacing.Left = 8 - BorderSpacing.Top = 2 - BorderSpacing.Right = 8 - Constraints.MinHeight = 200 - ItemHeight = 0 - OnSelectionChange = VarListSelectionChange - TabOrder = 0 - end - object GrpIn: TBitBtn - AnchorSideLeft.Control = Bevel3 - AnchorSideLeft.Side = asrBottom - AnchorSideTop.Control = VarList - Left = 209 - Height = 28 - Top = 25 - Width = 28 - Images = MainDataModule.ImageList - ImageIndex = 1 - OnClick = GrpInClick - Spacing = 0 - TabOrder = 1 - end - object GrpOut: TBitBtn - AnchorSideLeft.Control = Bevel3 - AnchorSideLeft.Side = asrBottom - AnchorSideTop.Control = GrpIn - AnchorSideTop.Side = asrBottom - Left = 209 - Height = 28 - Top = 57 - Width = 28 - BorderSpacing.Top = 4 - Images = MainDataModule.ImageList - ImageIndex = 0 - OnClick = GrpOutClick - Spacing = 0 - TabOrder = 2 - end - object DepIn: TBitBtn - AnchorSideLeft.Control = Bevel3 - AnchorSideLeft.Side = asrBottom - AnchorSideTop.Control = GrpOut - AnchorSideTop.Side = asrBottom - Left = 209 - Height = 28 - Top = 117 - Width = 28 - BorderSpacing.Top = 32 - Images = MainDataModule.ImageList - ImageIndex = 1 - OnClick = DepInClick - Spacing = 0 - TabOrder = 3 - end - object DepOut: TBitBtn - AnchorSideLeft.Control = Bevel3 - AnchorSideLeft.Side = asrBottom - AnchorSideTop.Control = DepIn - AnchorSideTop.Side = asrBottom - Left = 209 - Height = 28 - Top = 149 - Width = 28 - BorderSpacing.Top = 4 - Images = MainDataModule.ImageList - ImageIndex = 0 - OnClick = DepOutClick - Spacing = 0 - TabOrder = 4 - end - object GrpEdit: TEdit - AnchorSideLeft.Control = GrpIn - AnchorSideLeft.Side = asrBottom - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = GrpOut - AnchorSideBottom.Side = asrBottom - Left = 245 - Height = 23 - Top = 50 - Width = 120 - Anchors = [akLeft, akRight, akBottom] - BorderSpacing.Left = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 12 - ReadOnly = True - TabOrder = 5 - Text = 'GrpEdit' - end - object DepEdit: TEdit - AnchorSideLeft.Control = DepIn - AnchorSideLeft.Side = asrBottom - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = DepOut - AnchorSideBottom.Side = asrBottom - Left = 245 - Height = 23 - Top = 142 - Width = 120 - Anchors = [akLeft, akRight, akBottom] - BorderSpacing.Left = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 12 - ReadOnly = True - TabOrder = 6 - Text = 'Edit1' - end - object ResetBtn: TButton - AnchorSideRight.Control = ComputeBtn - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 164 - Height = 25 - Top = 288 - Width = 54 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 8 - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Reset' - OnClick = ResetBtnClick - TabOrder = 7 - end - object ComputeBtn: TButton - AnchorSideRight.Control = CloseBtn - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 226 - Height = 25 - Top = 288 - Width = 76 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Compute' - OnClick = ComputeBtnClick - TabOrder = 8 - end - object CloseBtn: TButton - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 310 - Height = 25 - Top = 288 - Width = 55 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Close' - ModalResult = 11 - TabOrder = 9 - end - object Bevel2: TBevel - AnchorSideLeft.Control = Owner - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = CloseBtn - Left = 0 - Height = 8 - Top = 272 - Width = 373 - Anchors = [akLeft, akRight, akBottom] - Shape = bsBottomLine - end - object Bevel3: TBevel - AnchorSideLeft.Control = Owner - AnchorSideLeft.Side = asrCenter - Left = 163 - Height = 11 - Top = 7 - Width = 46 - Shape = bsSpacer + inherited ParamsSplitter: TSplitter + Height = 400 end end diff --git a/applications/lazstats/source/forms/analysis/nonparametric/mannwhituunit.pas b/applications/lazstats/source/forms/analysis/nonparametric/mannwhituunit.pas index d45801b6c..c2b1a39e1 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/mannwhituunit.pas +++ b/applications/lazstats/source/forms/analysis/nonparametric/mannwhituunit.pas @@ -7,324 +7,291 @@ unit MannWhitUUnit; interface uses - Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Buttons, ExtCtrls, - MainUnit, OutputUnit, FunctionslIB, Globals, DataProcs; + MainUnit, FunctionslIB, Globals, DataProcs, BasicStatsReportFormUnit; type - { TMannWhitUFrm } + { TMannWhitUForm } - TMannWhitUFrm = class(TForm) - Bevel2: TBevel; + TMannWhitUForm = class(TBasicStatsReportForm) Bevel3: TBevel; GrpIn: TBitBtn; GrpOut: TBitBtn; DepIn: TBitBtn; DepOut: TBitBtn; - ResetBtn: TButton; - ComputeBtn: TButton; - CloseBtn: TButton; GrpEdit: TEdit; DepEdit: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; VarList: TListBox; - procedure ComputeBtnClick(Sender: TObject); procedure DepInClick(Sender: TObject); procedure DepOutClick(Sender: TObject); - procedure FormActivate(Sender: TObject); - procedure FormCreate(Sender: TObject); - procedure FormShow(Sender: TObject); procedure GrpInClick(Sender: TObject); procedure GrpOutClick(Sender: TObject); - procedure ResetBtnClick(Sender: TObject); + procedure VarListDblClick(Sender: TObject); procedure VarListSelectionChange(Sender: TObject; User: boolean); private - { private declarations } - FAutoSized: Boolean; - procedure UpdateBtnStates; + + protected + procedure AdjustConstraints; override; + procedure Compute; override; + procedure UpdateBtnStates; override; + public - { public declarations } + procedure Reset; override; end; var - MannWhitUFrm: TMannWhitUFrm; + MannWhitUForm: TMannWhitUForm; implementation +{$R *.lfm} + uses - Math; + Math, + Utils; -{ TMannWhitUFrm } +{ TMannWhitUForm } -procedure TMannWhitUFrm.ResetBtnClick(Sender: TObject); -var - i: integer; +procedure TMannWhitUForm.AdjustConstraints; begin - GrpEdit.Text := ''; - DepEdit.Text := ''; - VarList.Items.Clear; - for i := 1 to NoVariables do - VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); - UpdateBtnStates; + inherited; + + ParamsPanel.Constraints.MinWidth := 4*CloseBtn.Width + 3*CloseBtn.BorderSpacing.Left; + ParamsPanel.Constraints.MinHeight := DepOut.Top + DepOut.Height + + ButtonBevel.Height + CloseBtn.BorderSpacing.Top + CloseBtn.Height; end; -procedure TMannWhitUFrm.FormActivate(Sender: TObject); + +procedure TMannWhitUForm.Compute; var - w: Integer; + ColNoSelected: IntDyneVec = nil; + group_count: IntdyneVec = nil; + Ranks: DblDyneMat = nil; + X: DblDyneMat = nil; + RankSums: DblDyneVec = nil; + i, j, ind_var, dep_var, min_grp, max_grp, group, total_n : integer; + NoTies, NoTieGroups, n1, n2, nogroups, largestn : integer; + NoSelected : integer; + TieSum, score, t, SumT, Avg, z, prob, U, U2, SD, Temp : double; + cellstring, outline : string; + lReport: TStrings; + begin - if FAutoSized then + total_n := 0; + NoTieGroups := 0; + NoSelected := 2; + SumT := 0.0; + + // Check for data + if (NoVariables < 1) then + begin + ErrorMsg('You must have grid data!'); exit; - w := MaxValue([ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]); - ResetBtn.Constraints.MinWidth := w; - ComputeBtn.Constraints.MinWidth := w; - CloseBtn.Constraints.MinWidth := w; + end; - Constraints.MinWidth := (Label3.Width + GrpIn.Width + 2 * VarList.BorderSpacing.Left + Bevel3.Width div 2) * 2; - Constraints.MinHeight := Height; + // allocate space + SetLength(ColNoSelected, NoVariables); - FAutoSized := true; -end; + // Get column numbers of the independent and dependent variables + ind_var := 0; + dep_var := 0; + for i := 1 to NoVariables do + begin + cellstring := GrpEdit.Text; + if (cellstring = OS3MainFrm.DataGrid.Cells[i,0]) then ind_var := i; + cellstring := DepEdit.Text; + if (cellstring = OS3MainFrm.DataGrid.Cells[i,0]) then dep_var := i; + end; + ColNoSelected[0] := ind_var; + ColNoSelected[1] := dep_var; + if ind_var = 0 then + begin + ErrorMsg('No group variable.'); + exit; + end; + if dep_var = 0 then + begin + ErrorMsg('No dependent variable.'); + exit; + end; -procedure TMannWhitUFrm.FormCreate(Sender: TObject); -begin - Assert(OS3MainFrm <> nil); -end; + //get minimum and maximum group codes + min_grp := MaxInt; + max_grp := -MaxInt; + for i := 1 to NoCases do + begin + if (not GoodRecord(i, NoSelected, ColNoSelected)) then continue; + group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ind_var,i]))); + if (group < min_grp) then min_grp := group; + if (group > max_grp) then max_grp := group; + total_n := total_n + 1; + end; + nogroups := max_grp - min_grp + 1; -procedure TMannWhitUFrm.FormShow(Sender: TObject); -begin - ResetBtnClick(self); -end; + // Initialize arrays + SetLength(RankSums,nogroups); + SetLength(Ranks,NoCases,2); + SetLength(X,NoCases,2); + SetLength(group_count,nogroups); + for i := 0 to nogroups-1 do + begin + group_count[i] := 0; + RankSums[i] := 0.0; + end; -procedure TMannWhitUFrm.ComputeBtnClick(Sender: TObject); -var - i, j, ind_var, dep_var, min_grp, max_grp, group, total_n : integer; - NoTies, NoTieGroups, n1, n2, nogroups, largestn : integer; - NoSelected : integer; - ColNoSelected : IntDyneVec; - group_count : IntdyneVec; - Ranks, X : DblDyneMat; - RankSums : DblDyneVec; - TieSum, score, t, SumT, Avg, z, prob, U, U2, SD, Temp : double; - cellstring, outline : string; - lReport: TStrings; + // Setup for printer output + lReport := TStringList.Create; + try + lReport.Add('MANN-WHITNEY U TEST'); + lReport.Add('See pages 116-127 in S. Siegel: Nonparametric Statistics for the Behavioral Sciences'); + lReport.Add(''); -begin - total_n := 0; - NoTieGroups := 0; - NoSelected := 2; - SumT := 0.0; - - // Check for data - if (NoVariables < 1) then - begin - MessageDlg('You must have grid data!', mtError, [mbOK], 0); - exit; - end; - - // allocate space - SetLength(ColNoSelected,NoVariables); - - // Get column numbers of the independent and dependent variables - ind_var := 0; - dep_var := 0; - for i := 1 to NoVariables do - begin - cellstring := GrpEdit.Text; - if (cellstring = OS3MainFrm.DataGrid.Cells[i,0]) then ind_var := i; - cellstring := DepEdit.Text; - if (cellstring = OS3MainFrm.DataGrid.Cells[i,0]) then dep_var := i; - end; - ColNoSelected[0] := ind_var; - ColNoSelected[1] := dep_var; - if ind_var = 0 then - begin - MessageDlg('No group variable.', mtError, [mbOK], 0); - exit; - end; - if dep_var = 0 then - begin - MessageDlg('No dependent variable.', mtError, [mbOk], 0); - exit; - end; - - //get minimum and maximum group codes - min_grp := 10000; - max_grp := -10000; + // Get data for i := 1 to NoCases do begin - if (not GoodRecord(i,NoSelected,ColNoSelected)) then continue; - group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ind_var,i]))); - if (group < min_grp) then min_grp := group; - if (group > max_grp) then max_grp := group; - total_n := total_n + 1; + if (not GoodRecord(i,NoSelected,ColNoSelected)) then continue; + score := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[dep_var,i])); + group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ind_var,i]))); + group := group - min_grp + 1; + if (group > 2) then + begin + ErrorMsg('Group codes must be 1 and 2!'); + exit; + end; + group_count[group-1] := group_count[group-1] + 1; + X[i-1,0] := score; + X[i-1,1] := group; end; - nogroups := max_grp - min_grp + 1; - // Initialize arrays - SetLength(RankSums,nogroups); - SetLength(Ranks,NoCases,2); - SetLength(X,NoCases,2); - SetLength(group_count,nogroups); - for i := 0 to nogroups-1 do + // Sort all scores in ascending order + for i := 1 to total_n - 1 do begin - group_count[i] := 0; - RankSums[i] := 0.0; + for j := i + 1 to total_n do + begin + if (X[i-1,0] > X[j-1,0]) then + begin + Temp := X[i-1,0]; + X[i-1,0] := X[j-1,0]; + X[j-1,0] := Temp; + Temp := X[i-1,1]; + X[i-1,1] := X[j-1,1]; + X[j-1,1] := Temp; + end; + end; end; - // Setup for printer output - lReport := TStringList.Create; - try - lReport.Add('MANN-WHITNEY U TEST'); - lReport.Add('See pages 116-127 in S. Siegel: Nonparametric Statistics for the Behavioral Sciences'); - lReport.Add(''); - - // Get data - for i := 1 to NoCases do - begin - if (not GoodRecord(i,NoSelected,ColNoSelected)) then continue; - score := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[dep_var,i])); - group := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ind_var,i]))); - group := group - min_grp + 1; - if (group > 2) then - begin - MessageDlg('Group codes must be 1 and 2!', mtError, [mbOk], 0); - exit; - end; - group_count[group-1] := group_count[group-1] + 1; - X[i-1,0] := score; - X[i-1,1] := group; - end; - - //Sort all scores in ascending order - for i := 1 to total_n - 1 do - begin - for j := i + 1 to total_n do - begin - if (X[i-1,0] > X[j-1,0]) then - begin - Temp := X[i-1,0]; - X[i-1,0] := X[j-1,0]; - X[j-1,0] := Temp; - Temp := X[i-1,1]; - X[i-1,1] := X[j-1,1]; - X[j-1,1] := Temp; - end; - end; - end; - - // Store ranks - for i := 1 to total_n do - begin - Ranks[i-1,0] := i; - Ranks[i-1,1] := X[i-1,1]; - end; - - //Check for ties in ranks - replace with average rank and calculate - //T for each tie and sum of the T's - i := 1; - while i < total_n do - begin - j := i + 1; - TieSum := 0; - NoTies := 0; - while (j < total_n) do - begin - if (X[j-1,0] > X[i-1,0]) then - break; - if (X[j-1,0] = X[i-1,0]) then // match - begin - TieSum := TieSum + round(Ranks[j-1,0]); - NoTies := NoTies + 1; - end; - j := j + 1; - end; - - if (NoTies > 0) then //At least one tie found - begin - TieSum := TieSum + Ranks[i-1,0]; - NoTies := NoTies + 1; - Avg := TieSum / NoTies; - for j := i to i + NoTies - 1 do Ranks[j-1,0] := Avg; - t := Power(NoTies,3) - NoTies; - SumT := SumT + t; - NoTieGroups := NoTieGroups + 1; - i := i + (NoTies - 1); - end; - i := i + 1; - end; // next i - - // Calculate sum of ranks in each group - for i := 1 to total_n do - begin - group := round(Ranks[i-1,1]); - RankSums[group-1] := RankSums[group-1] + Ranks[i-1,0]; - end; - - //Calculate U for larger and smaller groups - n1 := group_count[0]; - n2 := group_count[1]; - if (n1 > n2) then - U := n1 * n2 + n1 * (n1 + 1) / 2.0 - RankSums[0] - else - U := n1 * n2 + n2 * (n2 + 1) / 2.0 - RankSums[1]; - U2 := n1 * n2 - U; - SD := n1 * n2 * (n1 + n2 + 1) / 12.0; - SD := sqrt(SD); - if (U2 > U) then - z := (U2 - n1 * n2 / 2) / SD - else - z := (U - n1 * n2 / 2) / SD; - prob := 1.0 - probz(z); - - //Report results - lReport.Add(' Score Rank Group'); - lReport.Add(''); - for i := 1 to total_n do - lReport.Add('%10.2f %10.2f %10.0f', [X[i-1,0], Ranks[i-1,0], Ranks[i-1,1]]); - lReport.Add(''); - lReport.Add('Sum of Ranks in each Group'); - lReport.Add('Group Sum No. in Group'); - for i := 1 to nogroups do - lReport.Add('%3d %10.2f %5d', [i+min_grp-1, RankSums[i-1], group_count[i-1]]); - lReport.Add(''); - lReport.Add('No. of tied rank groups: %10d', [NoTieGroups]); - if (n1 > n2) then - largestn := n1 - else - largestn := n2; - if (largestn < 20) then - outline := format('Statistic U: %26.4f',[U]) - else - begin - if (U > U2) then - outline := format('Statistic U: %26.4f',[U]) - else - outline := format('Statistic U: %26.4f',[U2]); - end; - lReport.Add(outline); - lReport.Add('z Statistic (corrected for ties): %8.4f', [z]); - lReport.Add(' Probability > z: %8.4f', [prob]); - if (n2 < 20) then - begin - lReport.Add('z test is approximate. Use tables of exact probabilities in Siegel.'); - lReport.Add('(Table J or K, pages 271-277)'); - end; - DisplayReport(lReport); - - finally - lReport.Free; - group_count := nil; - X := nil; - Ranks := nil; - RankSums := nil; - ColNoSelected := nil; + // Store ranks + for i := 1 to total_n do + begin + Ranks[i-1,0] := i; + Ranks[i-1,1] := X[i-1,1]; end; + + // Check for ties in ranks - replace with average rank and calculate + // T for each tie and sum of the T's + i := 1; + while i < total_n do + begin + j := i + 1; + TieSum := 0; + NoTies := 0; + while (j < total_n) do + begin + if (X[j-1,0] > X[i-1,0]) then + break; + if (X[j-1,0] = X[i-1,0]) then // match + begin + TieSum := TieSum + round(Ranks[j-1,0]); + NoTies := NoTies + 1; + end; + j := j + 1; + end; + + if (NoTies > 0) then //At least one tie found + begin + TieSum := TieSum + Ranks[i-1,0]; + NoTies := NoTies + 1; + Avg := TieSum / NoTies; + for j := i to i + NoTies - 1 do Ranks[j-1,0] := Avg; + t := Power(NoTies,3) - NoTies; + SumT := SumT + t; + NoTieGroups := NoTieGroups + 1; + i := i + (NoTies - 1); + end; + i := i + 1; + end; // next i + + // Calculate sum of ranks in each group + for i := 1 to total_n do + begin + group := round(Ranks[i-1,1]); + RankSums[group-1] := RankSums[group-1] + Ranks[i-1,0]; + end; + + // Calculate U for larger and smaller groups + n1 := group_count[0]; + n2 := group_count[1]; + if (n1 > n2) then + U := n1 * n2 + n1 * (n1 + 1) / 2.0 - RankSums[0] + else + U := n1 * n2 + n2 * (n2 + 1) / 2.0 - RankSums[1]; + U2 := n1 * n2 - U; + SD := n1 * n2 * (n1 + n2 + 1) / 12.0; + SD := sqrt(SD); + if (U2 > U) then + z := (U2 - n1 * n2 / 2) / SD + else + z := (U - n1 * n2 / 2) / SD; + prob := 1.0 - probz(z); + + // Report results + lReport.Add(' Score Rank Group'); + lReport.Add(''); + for i := 1 to total_n do + lReport.Add('%10.2f %10.2f %10.0f', [X[i-1,0], Ranks[i-1,0], Ranks[i-1,1]]); + lReport.Add(''); + lReport.Add('Sum of Ranks in each Group'); + lReport.Add('Group Sum No. in Group'); + for i := 1 to nogroups do + lReport.Add('%3d %10.2f %5d', [i+min_grp-1, RankSums[i-1], group_count[i-1]]); + lReport.Add(''); + lReport.Add('No. of tied rank groups: %10d', [NoTieGroups]); + if (n1 > n2) then + largestn := n1 + else + largestn := n2; + if (largestn < 20) then + outline := format('Statistic U: %26.4f',[U]) + else + begin + if (U > U2) then + outline := format('Statistic U: %26.4f',[U]) + else + outline := format('Statistic U: %26.4f',[U2]); + end; + lReport.Add(outline); + lReport.Add('z Statistic (corrected for ties): %8.4f', [z]); + lReport.Add(' Probability > z: %8.4f', [prob]); + if (n2 < 20) then + begin + lReport.Add('z test is approximate. Use tables of exact probabilities in Siegel.'); + lReport.Add('(Table J or K, pages 271-277)'); + end; + + FReportFrame.DisplayReport(lReport); + + finally + lReport.Free; + end; end; -procedure TMannWhitUFrm.DepInClick(Sender: TObject); + +procedure TMannWhitUForm.DepInClick(Sender: TObject); var index: integer; begin @@ -337,7 +304,8 @@ begin UpdateBtnStates; end; -procedure TMannWhitUFrm.DepOutClick(Sender: TObject); + +procedure TMannWhitUForm.DepOutClick(Sender: TObject); begin if DepEdit.Text <> '' then begin @@ -347,7 +315,8 @@ begin UpdateBtnStates; end; -procedure TMannWhitUFrm.GrpInClick(Sender: TObject); + +procedure TMannWhitUForm.GrpInClick(Sender: TObject); var index: integer; begin @@ -360,7 +329,8 @@ begin UpdateBtnStates; end; -procedure TMannWhitUFrm.GrpOutClick(Sender: TObject); + +procedure TMannWhitUForm.GrpOutClick(Sender: TObject); begin if GrpEdit.Text <> '' then begin @@ -370,21 +340,54 @@ begin UpdateBtnStates; end; -procedure TMannWhitUFrm.UpdateBtnStates; + +procedure TMannWhitUForm.Reset; +var + i: integer; begin + inherited; + GrpEdit.Clear; + DepEdit.clear; + VarList.Items.Clear; + for i := 1 to NoVariables do + VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); + UpdateBtnStates; +end; + + +procedure TMannWhitUForm.UpdateBtnStates; +begin + inherited; GrpIn.Enabled := (VarList.ItemIndex > -1) and (GrpEdit.Text = ''); DepIn.Enabled := (VarList.ItemIndex > -1) and (DepEdit.Text = ''); GrpOut.Enabled := GrpEdit.Text <> ''; DepOut.Enabled := DepEdit.Text <> ''; end; -procedure TMannWhitUFrm.VarListSelectionChange(Sender: TObject; User: boolean); + +procedure TMannWhitUForm.VarListDblClick(Sender: TObject); +var + index: Integer; + s: String; +begin + index := VarList.ItemIndex; + if index > -1 then + begin + s := VarList.Items[index]; + if GrpEdit.Text = '' then + GrpEdit.Text := s + else if DepEdit.Text = '' then + DepEdit.Text := s; + VarList.Items.Delete(index); + UpdateBtnStates; + end; +end; + + +procedure TMannWhitUForm.VarListSelectionChange(Sender: TObject; User: boolean); begin UpdateBtnStates; end; -initialization - {$I mannwhituunit.lrs} - end. diff --git a/applications/lazstats/source/forms/analysis/nonparametric/runstestunit.lfm b/applications/lazstats/source/forms/analysis/nonparametric/runstestunit.lfm index cb242cbda..530dbdd75 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/runstestunit.lfm +++ b/applications/lazstats/source/forms/analysis/nonparametric/runstestunit.lfm @@ -1,7 +1,7 @@ object runstestform: Trunstestform - Left = 476 + Left = 1138 Height = 438 - Top = 209 + Top = 277 Width = 376 HelpType = htKeyword HelpKeyword = 'html/RunsTestforNormality.htm' diff --git a/applications/lazstats/source/forms/analysis/nonparametric/signtestunit.lfm b/applications/lazstats/source/forms/analysis/nonparametric/signtestunit.lfm index a2ee18137..1f72ce8be 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/signtestunit.lfm +++ b/applications/lazstats/source/forms/analysis/nonparametric/signtestunit.lfm @@ -1,32 +1,32 @@ inherited SignTestFrm: TSignTestFrm Left = 550 - Height = 345 + Height = 344 Top = 297 - Width = 382 + Width = 561 Caption = 'The Matched Pairs Sign Test' - ClientHeight = 345 - ClientWidth = 382 + ClientHeight = 344 + ClientWidth = 561 inherited ParamsPanel: TPanel - Height = 329 - ClientHeight = 329 + Height = 328 + ClientHeight = 328 inherited CloseBtn: TButton - Top = 304 + Top = 303 TabOrder = 10 end inherited ComputeBtn: TButton - Top = 304 + Top = 303 TabOrder = 9 end inherited ResetBtn: TButton - Top = 304 + Top = 303 TabOrder = 8 end inherited HelpBtn: TButton - Top = 304 + Top = 303 TabOrder = 7 end inherited ButtonBevel: TBevel - Top = 288 + Top = 287 end object Label1: TLabel[5] AnchorSideLeft.Control = ParamsPanel @@ -69,7 +69,7 @@ inherited SignTestFrm: TSignTestFrm AnchorSideRight.Control = Var1In AnchorSideBottom.Control = ButtonBevel Left = 0 - Height = 271 + Height = 270 Top = 17 Width = 126 Anchors = [akTop, akLeft, akRight, akBottom] @@ -180,6 +180,6 @@ inherited SignTestFrm: TSignTestFrm end end inherited ParamsSplitter: TSplitter - Height = 345 + Height = 344 end end diff --git a/applications/lazstats/source/forms/mainunit.pas b/applications/lazstats/source/forms/mainunit.pas index d696550d5..a6b022c4d 100644 --- a/applications/lazstats/source/forms/mainunit.pas +++ b/applications/lazstats/source/forms/mainunit.pas @@ -1824,9 +1824,9 @@ end; // Menu "Analysis" > "Nonparametric" > "Mann-Whitney U Test" procedure TOS3MainFrm.mnuAnalysisNonPar_MannWhitneyClick(Sender: TObject); begin - if MannWhitUFrm = nil then - Application.CreateForm(TMannWhitUFrm, MannWhitUFrm); - MannWhitUFrm.ShowModal; + if MannWhitUForm = nil then + Application.CreateForm(TMannWhitUForm, MannWhitUForm); + MannWhitUForm.Show; end; // Menu "Analysis" > "Nonparametric" > "Fisher's Exact Text"