diff --git a/applications/lazstats/source/LazStats.lpi b/applications/lazstats/source/LazStats.lpi index aeac427d7..e72d67074 100644 --- a/applications/lazstats/source/LazStats.lpi +++ b/applications/lazstats/source/LazStats.lpi @@ -705,7 +705,7 @@ - + @@ -713,7 +713,7 @@ - + @@ -753,7 +753,7 @@ - + diff --git a/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.lfm b/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.lfm index 2e031bcfd..b727186c3 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.lfm +++ b/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.lfm @@ -1,4 +1,4 @@ -inherited ChiSqrFrm: TChiSqrFrm +inherited ChiSqrForm: TChiSqrForm Left = 425 Height = 503 Top = 216 diff --git a/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.pas b/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.pas index 75a8519a9..99d0ada5e 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.pas +++ b/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.pas @@ -12,9 +12,9 @@ uses type - { TChiSqrFrm } + { TChiSqrForm } - TChiSqrFrm = class(TBasicStatsReportForm) + TChiSqrForm = class(TBasicStatsReportForm) ObsChk: TCheckBox; ExpChk: TCheckBox; PageControl: TPageControl; @@ -111,7 +111,7 @@ type end; var - ChiSqrFrm: TChiSqrFrm; + ChiSqrForm: TChiSqrForm; implementation @@ -121,9 +121,9 @@ uses Math, Utils, GridProcs, MatrixUnit; -{ TChiSqrFrm } +{ TChiSqrForm } -constructor TChiSqrFrm.Create(AOwner: TComponent); +constructor TChiSqrForm.Create(AOwner: TComponent); begin inherited; if DictionaryFrm = nil then @@ -170,7 +170,7 @@ begin end; -procedure TChiSqrFrm.AdjustConstraints; +procedure TChiSqrForm.AdjustConstraints; begin inherited; @@ -185,7 +185,7 @@ begin end; -function TChiSqrFrm.CalcGStatistic(const AFrequencies: IntDyneMat; +function TChiSqrForm.CalcGStatistic(const AFrequencies: IntDyneMat; const AExpected: DblDyneMat): Double; var numRows, numCols: Integer; @@ -201,7 +201,7 @@ begin end; -function TChiSqrFrm.CalcLikelihoodRatio(const AFrequencies: IntDyneMat; +function TChiSqrForm.CalcLikelihoodRatio(const AFrequencies: IntDyneMat; const AExpected: DblDyneMat): Double; var numRows, numCols: Integer; @@ -217,7 +217,7 @@ begin end; -function TChiSqrFrm.CalcPearsonR(const AFrequencies: IntDyneMat): Double; +function TChiSqrForm.CalcPearsonR(const AFrequencies: IntDyneMat): Double; var numRows, numCols, numCases: Integer; sumX, sumY: Double; @@ -254,7 +254,7 @@ begin Result := Result / sqrt(varX * varY); end; -procedure TChiSqrFrm.ColInClick(Sender: TObject); +procedure TChiSqrForm.ColInClick(Sender: TObject); var index: integer; begin @@ -268,7 +268,7 @@ begin end; -procedure TChiSqrFrm.ColOutClick(Sender: TObject); +procedure TChiSqrForm.ColOutClick(Sender: TObject); begin if ColEdit.Text <> '' then begin @@ -279,7 +279,7 @@ begin end; -procedure TChiSqrFrm.Compute; +procedure TChiSqrForm.Compute; var ColNoSelected: IntDyneVec = nil; Freq: IntDyneMat = nil; @@ -434,7 +434,7 @@ begin end; -procedure TChiSqrFrm.DepInClick(Sender: TObject); +procedure TChiSqrForm.DepInClick(Sender: TObject); var index: integer; begin @@ -448,7 +448,7 @@ begin end; -procedure TChiSqrFrm.DepOutClick(Sender: TObject); +procedure TChiSqrForm.DepOutClick(Sender: TObject); begin if DepEdit.Text <> '' then begin @@ -459,7 +459,7 @@ begin end; -procedure TChiSqrFrm.FrequenciesToGrid(const AFrequencies: IntDyneMat); +procedure TChiSqrForm.FrequenciesToGrid(const AFrequencies: IntDyneMat); var numRows, numCols: Integer; row, col: Integer; @@ -514,7 +514,7 @@ begin end; -procedure TChiSqrFrm.GetExpectedAndCellChiSqr(const AFrequencies: IntDyneMat; +procedure TChiSqrForm.GetExpectedAndCellChiSqr(const AFrequencies: IntDyneMat; out AExpected, ACellChiSqr: DblDyneMat; out AChiSqr: Double); var @@ -547,7 +547,7 @@ begin end; -procedure TChiSqrFrm.GetFrequencies(const AColNoSelected: IntDyneVec; +procedure TChiSqrForm.GetFrequencies(const AColNoSelected: IntDyneVec; ARowIndex, AColIndex, ADepIndex: Integer; out ANumRows, ANumCols, ANumCases: Integer; out AFrequencies: IntDyneMat); var @@ -636,7 +636,7 @@ end; // 2 x 2 corrected chi-square -procedure TChiSqrFrm.GetYatesCorrection(const AFrequencies: IntDyneMat; +procedure TChiSqrForm.GetYatesCorrection(const AFrequencies: IntDyneMat; out AdjChiSqr: Double); var n, m, numCases: Integer; @@ -650,7 +650,7 @@ begin end; -procedure TChiSqrFrm.GetColProportions(const AFrequencies: IntDyneMat; +procedure TChiSqrForm.GetColProportions(const AFrequencies: IntDyneMat; out AProportions: DblDyneMat); var numRows, numCols: Integer; @@ -676,7 +676,7 @@ begin end; -procedure TChiSqrFrm.GetRowProportions(const AFrequencies: IntDyneMat; +procedure TChiSqrForm.GetRowProportions(const AFrequencies: IntDyneMat; out AProportions: DblDyneMat); var numRows, numCols: Integer; @@ -702,7 +702,7 @@ begin end; -procedure TChiSqrFrm.GetTotalProportions(const AFrequencies: IntDyneMat; +procedure TChiSqrForm.GetTotalProportions(const AFrequencies: IntDyneMat; out AProportions: DblDyneMat); var numRows, numCols, numCases: Integer; @@ -720,7 +720,7 @@ begin end; -procedure TChiSqrFrm.InputGrpClick(Sender: TObject); +procedure TChiSqrForm.InputGrpClick(Sender: TObject); begin // InputGrp = 0: have to count cases in each row and col combination // = 1: frequencies available for each row and column combo @@ -735,7 +735,7 @@ begin end; -procedure TChiSqrFrm.ProcessAndReportCellChiSqr(const ACellChiSqr: DblDyneMat; +procedure TChiSqrForm.ProcessAndReportCellChiSqr(const ACellChiSqr: DblDyneMat; const ARowLabels, AColLabels: StrDyneVec; ANumCases: Integer); var lReport: TStrings; @@ -755,7 +755,7 @@ begin end; -procedure TChiSqrFrm.ProcessAndReportFrequencies(const AFrequencies: IntDyneMat; +procedure TChiSqrForm.ProcessAndReportFrequencies(const AFrequencies: IntDyneMat; const AExpected: DblDyneMat; const ARowLabels, AColLabels: StrDyneVec); var lReport: TStrings; @@ -789,7 +789,7 @@ begin end; -procedure TChiSqrFrm.ProcessAndReportProportions(const AFrequencies: IntDyneMat; +procedure TChiSqrForm.ProcessAndReportProportions(const AFrequencies: IntDyneMat; const ARowLabels, AColLabels: StrDyneVec); var lReport: TStrings; @@ -826,7 +826,7 @@ begin end; -procedure TChiSqrFrm.Reset; +procedure TChiSqrForm.Reset; var i: integer; begin @@ -868,7 +868,7 @@ begin end; -procedure TChiSqrFrm.RowInClick(Sender: TObject); +procedure TChiSqrForm.RowInClick(Sender: TObject); var index: integer; begin @@ -882,7 +882,7 @@ begin end; -procedure TChiSqrFrm.RowOutClick(Sender: TObject); +procedure TChiSqrForm.RowOutClick(Sender: TObject); begin if RowEdit.Text <> '' then begin @@ -893,7 +893,7 @@ begin end; -procedure TChiSqrFrm.UpdateBtnStates; +procedure TChiSqrForm.UpdateBtnStates; begin inherited; @@ -914,7 +914,7 @@ begin end; -function TChiSqrFrm.Validate(out AMsg: String; out AControl: TWinControl): Boolean; +function TChiSqrForm.Validate(out AMsg: String; out AControl: TWinControl): Boolean; var n: Integer; begin @@ -962,7 +962,7 @@ begin end; -procedure TChiSqrFrm.VarListDblClick(Sender: TObject); +procedure TChiSqrForm.VarListDblClick(Sender: TObject); var index: Integer; s: String; @@ -983,7 +983,7 @@ begin end; -procedure TChiSqrFrm.VarListSelectionChange(Sender: TObject; User: boolean); +procedure TChiSqrForm.VarListSelectionChange(Sender: TObject; User: boolean); begin UpdateBtnStates; end; diff --git a/applications/lazstats/source/forms/analysis/nonparametric/spearmanunit.lfm b/applications/lazstats/source/forms/analysis/nonparametric/spearmanunit.lfm index 3fd5ecacf..00d373ef5 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/spearmanunit.lfm +++ b/applications/lazstats/source/forms/analysis/nonparametric/spearmanunit.lfm @@ -1,4 +1,4 @@ -inherited SpearmanFrm: TSpearmanFrm +inherited SpearmanForm: TSpearmanForm Left = 531 Height = 347 Top = 246 diff --git a/applications/lazstats/source/forms/analysis/nonparametric/spearmanunit.pas b/applications/lazstats/source/forms/analysis/nonparametric/spearmanunit.pas index df04353e5..41bb9b7a4 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/spearmanunit.pas +++ b/applications/lazstats/source/forms/analysis/nonparametric/spearmanunit.pas @@ -11,9 +11,9 @@ uses type - { TSpearmanFrm } + { TSpearmanForm } - TSpearmanFrm = class(TBasicStatsReportForm) + TSpearmanForm = class(TBasicStatsReportForm) Bevel1: TBevel; XIn: TBitBtn; XOut: TBitBtn; @@ -37,13 +37,14 @@ type 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 - SpearmanFrm: TSpearmanFrm; + SpearmanForm: TSpearmanForm; implementation @@ -53,9 +54,9 @@ implementation uses Math, MathUnit; -{ TSpearmanFrm } +{ TSpearmanForm } -procedure TSpearmanFrm.AdjustConstraints; +procedure TSpearmanForm.AdjustConstraints; begin inherited; @@ -66,7 +67,7 @@ begin end; -procedure TSpearmanFrm.Compute; +procedure TSpearmanForm.Compute; var index: IntDyneMat = nil; Ranks: DblDyneMat = nil; @@ -82,15 +83,6 @@ var VarX, VarY, SDX, SDY, MeanX, MeanY, Rxy: double; lReport: TStrings; begin - if (XEdit.Text = '') then begin - MessageDlg('X variable is not selected.', mtError, [mbOK], 0); - exit; - end; - if (YEdit.Text = '') then begin - MessageDlg('Y variable is not selected.', mtError, [mbOK], 0); - exit; - end; - // Allocate memory SetLength(ColNoSelected, NoVariables); SetLength(index, NoCases, 2); @@ -368,7 +360,7 @@ begin end; -procedure TSpearmanFrm.Reset; +procedure TSpearmanForm.Reset; var i: integer; begin @@ -384,7 +376,7 @@ begin end; -procedure TSpearmanFrm.UpdateBtnStates; +procedure TSpearmanForm.UpdateBtnStates; begin inherited; @@ -395,13 +387,33 @@ begin end; -procedure TSpearmanFrm.VarListSelectionChange(Sender: TObject; User: boolean); +function TSpearmanForm.Validate(out AMsg: String; out AControl: TWinControl): boolean; +begin + Result := false; + + if (XEdit.Text = '') then begin + AMsg := 'X variable is not selected.'; + AControl := XEdit; + exit; + end; + + if (YEdit.Text = '') then begin + AMsg := 'Y variable is not selected.'; + AControl := YEdit; + exit; + end; + + Result := true; +end; + + +procedure TSpearmanForm.VarListSelectionChange(Sender: TObject; User: boolean); begin UpdateBtnStates; end; -procedure TSpearmanFrm.VarListDblClick(Sender: TObject); +procedure TSpearmanForm.VarListDblClick(Sender: TObject); var index: Integer; s: String; @@ -420,7 +432,7 @@ begin end; -procedure TSpearmanFrm.XInClick(Sender: TObject); +procedure TSpearmanForm.XInClick(Sender: TObject); var index: integer; begin @@ -434,7 +446,7 @@ begin end; -procedure TSpearmanFrm.XOutClick(Sender: TObject); +procedure TSpearmanForm.XOutClick(Sender: TObject); begin if XEdit.Text <> '' then begin @@ -445,7 +457,7 @@ begin end; -procedure TSpearmanFrm.YInClick(Sender: TObject); +procedure TSpearmanForm.YInClick(Sender: TObject); var index: integer; begin @@ -459,7 +471,7 @@ begin end; -procedure TSpearmanFrm.YOutClick(Sender: TObject); +procedure TSpearmanForm.YOutClick(Sender: TObject); begin if YEdit.Text <> '' then begin diff --git a/applications/lazstats/source/forms/analysis/nonparametric/wilcoxonunit.lfm b/applications/lazstats/source/forms/analysis/nonparametric/wilcoxonunit.lfm index 0cc1a16aa..79ce5ad4b 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/wilcoxonunit.lfm +++ b/applications/lazstats/source/forms/analysis/nonparametric/wilcoxonunit.lfm @@ -1,267 +1,184 @@ -object WilcoxonFrm: TWilcoxonFrm +inherited WilcoxonForm: TWilcoxonForm Left = 498 - Height = 352 + Height = 294 Top = 336 - Width = 436 + Width = 478 HelpType = htKeyword HelpKeyword = 'html/WilcoxonMatched-PairsSignedRanks.htm' - AutoSize = True - BorderStyle = bsDialog Caption = 'Wilcoxon Matched Pairs Signed Ranks Test' - ClientHeight = 352 - ClientWidth = 436 - 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 - end - object Label2: TLabel - AnchorSideLeft.Control = Var1Edit - AnchorSideBottom.Control = Var1Edit - Left = 240 - Height = 15 - Top = 33 - Width = 50 - Anchors = [akLeft, akBottom] - BorderSpacing.Bottom = 2 - Caption = 'Variable 1' - ParentColor = False - end - object Label3: TLabel - AnchorSideLeft.Control = Var2Edit - AnchorSideBottom.Control = Var2Edit - Left = 240 - Height = 15 - Top = 125 - Width = 50 - Anchors = [akLeft, akBottom] - BorderSpacing.Bottom = 2 - Caption = 'Variable 2' - ParentColor = False - end - object VarList: TListBox - AnchorSideLeft.Control = Owner - AnchorSideTop.Control = Label1 - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = Var1In - AnchorSideBottom.Control = Bevel1 - Left = 9 + ClientHeight = 294 + ClientWidth = 478 + inherited ParamsPanel: TPanel Height = 278 - Top = 25 - Width = 187 - Anchors = [akTop, akLeft, akRight, akBottom] - BorderSpacing.Left = 9 - BorderSpacing.Top = 2 - BorderSpacing.Right = 8 - Constraints.MinHeight = 200 - ItemHeight = 0 - OnSelectionChange = VarListSelectionChange - TabOrder = 0 + ClientHeight = 278 + inherited CloseBtn: TButton + Top = 253 + end + inherited ComputeBtn: TButton + Top = 253 + end + inherited ResetBtn: TButton + Top = 253 + end + inherited HelpBtn: TButton + Top = 253 + end + inherited ButtonBevel: TBevel + Top = 237 + 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 = Var1Edit + AnchorSideBottom.Control = Var1Edit + Left = 166 + Height = 15 + Top = 21 + Width = 50 + Anchors = [akLeft, akBottom] + BorderSpacing.Bottom = 2 + Caption = 'Variable 1' + ParentColor = False + end + object Label3: TLabel[7] + AnchorSideLeft.Control = Var2Edit + AnchorSideBottom.Control = Var2Edit + Left = 166 + Height = 15 + Top = 109 + Width = 50 + Anchors = [akLeft, akBottom] + BorderSpacing.Bottom = 2 + Caption = 'Variable 2' + ParentColor = False + end + object VarList: TListBox[8] + AnchorSideLeft.Control = ParamsPanel + AnchorSideTop.Control = Label1 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = Var1In + AnchorSideBottom.Control = ButtonBevel + Left = 0 + Height = 220 + 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 Var1In: 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 = Var1InClick + Spacing = 0 + TabOrder = 5 + end + object Var1Out: TBitBtn[10] + AnchorSideLeft.Control = ParamsPanel + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = Var1In + AnchorSideTop.Side = asrBottom + Left = 132 + Height = 26 + Top = 47 + Width = 26 + BorderSpacing.Top = 4 + Images = MainDataModule.ImageList + ImageIndex = 0 + OnClick = Var1OutClick + Spacing = 0 + TabOrder = 6 + end + object Var2In: TBitBtn[11] + AnchorSideLeft.Control = ParamsPanel + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = Var1Out + AnchorSideTop.Side = asrBottom + Left = 132 + Height = 26 + Top = 105 + Width = 26 + BorderSpacing.Top = 32 + Images = MainDataModule.ImageList + ImageIndex = 1 + OnClick = Var2InClick + Spacing = 0 + TabOrder = 7 + end + object Var2Out: TBitBtn[12] + AnchorSideLeft.Control = ParamsPanel + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = Var2In + AnchorSideTop.Side = asrBottom + Left = 132 + Height = 26 + Top = 135 + Width = 26 + BorderSpacing.Top = 4 + Images = MainDataModule.ImageList + ImageIndex = 0 + OnClick = Var2OutClick + Spacing = 0 + TabOrder = 8 + end + object Var1Edit: TEdit[13] + AnchorSideLeft.Control = Var1In + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = ParamsPanel + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Var1Out + AnchorSideBottom.Side = asrBottom + Left = 166 + Height = 23 + Top = 38 + Width = 125 + Anchors = [akLeft, akRight, akBottom] + BorderSpacing.Left = 8 + BorderSpacing.Bottom = 12 + ReadOnly = True + TabOrder = 9 + Text = 'Var1Edit' + end + object Var2Edit: TEdit[14] + AnchorSideLeft.Control = Var2In + AnchorSideLeft.Side = asrBottom + AnchorSideRight.Control = ParamsPanel + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Var2Out + AnchorSideBottom.Side = asrBottom + Left = 166 + Height = 23 + Top = 126 + Width = 125 + Anchors = [akLeft, akRight, akBottom] + BorderSpacing.Left = 8 + BorderSpacing.Bottom = 12 + ReadOnly = True + TabOrder = 10 + Text = 'Var2Edit' + end end - object Var1In: TBitBtn - AnchorSideLeft.Control = Owner - AnchorSideLeft.Side = asrCenter - AnchorSideTop.Control = VarList - Left = 204 - Height = 28 - Top = 25 - Width = 28 - Images = MainDataModule.ImageList - ImageIndex = 1 - OnClick = Var1InClick - Spacing = 0 - TabOrder = 1 - end - object Var1Out: TBitBtn - AnchorSideLeft.Control = Owner - AnchorSideLeft.Side = asrCenter - AnchorSideTop.Control = Var1In - AnchorSideTop.Side = asrBottom - Left = 204 - Height = 28 - Top = 57 - Width = 28 - BorderSpacing.Top = 4 - Images = MainDataModule.ImageList - ImageIndex = 0 - OnClick = Var1OutClick - Spacing = 0 - TabOrder = 2 - end - object Var2In: TBitBtn - AnchorSideLeft.Control = Owner - AnchorSideLeft.Side = asrCenter - AnchorSideTop.Control = Var1Out - AnchorSideTop.Side = asrBottom - Left = 204 - Height = 28 - Top = 117 - Width = 28 - BorderSpacing.Top = 32 - Images = MainDataModule.ImageList - ImageIndex = 1 - OnClick = Var2InClick - Spacing = 0 - TabOrder = 4 - end - object Var2Out: TBitBtn - AnchorSideLeft.Control = Owner - AnchorSideLeft.Side = asrCenter - AnchorSideTop.Control = Var2In - AnchorSideTop.Side = asrBottom - Left = 204 - Height = 28 - Top = 149 - Width = 28 - BorderSpacing.Top = 4 - Images = MainDataModule.ImageList - ImageIndex = 0 - OnClick = Var2OutClick - Spacing = 0 - TabOrder = 5 - end - object Var1Edit: TEdit - AnchorSideLeft.Control = Var1In - AnchorSideLeft.Side = asrBottom - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = Var1Out - AnchorSideBottom.Side = asrBottom - Left = 240 - Height = 23 - Top = 50 - Width = 188 - Anchors = [akLeft, akRight, akBottom] - BorderSpacing.Left = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 12 - ReadOnly = True - TabOrder = 3 - Text = 'Var1Edit' - end - object Var2Edit: TEdit - AnchorSideLeft.Control = Var2In - AnchorSideLeft.Side = asrBottom - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = Var2Out - AnchorSideBottom.Side = asrBottom - Left = 240 - Height = 23 - Top = 142 - Width = 188 - Anchors = [akLeft, akRight, akBottom] - BorderSpacing.Left = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 12 - ReadOnly = True - TabOrder = 6 - Text = 'Var2Edit' - end - object ResetBtn: TButton - AnchorSideRight.Control = ComputeBtn - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 227 - Height = 25 - Top = 319 - Width = 54 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 8 - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Reset' - OnClick = ResetBtnClick - TabOrder = 8 - end - object ComputeBtn: TButton - AnchorSideRight.Control = CloseBtn - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 289 - Height = 25 - Top = 319 - Width = 76 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 8 - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Compute' - OnClick = ComputeBtnClick - TabOrder = 9 - end - object CloseBtn: TButton - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 373 - Height = 25 - Top = 319 - Width = 55 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 8 - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Close' - ModalResult = 11 - TabOrder = 10 - end - object HelpBtn: TButton - Tag = 156 - AnchorSideRight.Control = ResetBtn - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 168 - Height = 25 - Top = 319 - Width = 51 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 8 - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Help' - OnClick = HelpBtnClick - TabOrder = 7 - end - object Bevel1: TBevel - AnchorSideLeft.Control = Owner - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = CloseBtn - Left = 0 - Height = 8 - Top = 303 - Width = 436 - Anchors = [akLeft, akRight, akBottom] - Shape = bsBottomLine - end - object Bevel2: TBevel - Left = 3 - Height = 20 - Top = 336 - Width = 16 - Shape = bsSpacer + inherited ParamsSplitter: TSplitter + Height = 294 end end diff --git a/applications/lazstats/source/forms/analysis/nonparametric/wilcoxonunit.pas b/applications/lazstats/source/forms/analysis/nonparametric/wilcoxonunit.pas index ee9b3a6eb..632562a60 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/wilcoxonunit.pas +++ b/applications/lazstats/source/forms/analysis/nonparametric/wilcoxonunit.pas @@ -5,21 +5,15 @@ unit WilcoxonUnit; 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, ContextHelpUnit; + MainUnit, FunctionsLib, Globals, DataProcs, BasicStatsReportFormUnit; type - { TWilcoxonFrm } + { TWilcoxonForm } - TWilcoxonFrm = class(TForm) - Bevel1: TBevel; - Bevel2: TBevel; - HelpBtn: TButton; - ResetBtn: TButton; - ComputeBtn: TButton; - CloseBtn: TButton; + TWilcoxonForm = class(TBasicStatsReportForm) Var1Edit: TEdit; Var2Edit: TEdit; Label2: TLabel; @@ -30,48 +24,261 @@ type Var2Out: TBitBtn; Label1: TLabel; VarList: TListBox; - procedure ComputeBtnClick(Sender: TObject); - procedure FormActivate(Sender: TObject); - procedure FormCreate(Sender: TObject); - procedure FormShow(Sender: TObject); - procedure HelpBtnClick(Sender: TObject); - procedure ResetBtnClick(Sender: TObject); procedure Var1InClick(Sender: TObject); procedure Var1OutClick(Sender: TObject); procedure Var2InClick(Sender: TObject); procedure Var2OutClick(Sender: TObject); - procedure VarListSelectionChange(Sender: TObject; User: boolean); + procedure VarListDblClick(Sender: TObject); + procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean); private - { private declarations } - FAutoSized: Boolean; - procedure UpdateBtnStates; + + protected + procedure AdjustConstraints; override; + procedure Compute; override; + procedure UpdateBtnStates; override; + function Validate(out AMsg: String; out AControl: TWinControl): Boolean; override; + public - { public declarations } + procedure Reset; override; end; var - WilcoxonFrm: TWilcoxonFrm; + WilcoxonForm: TWilcoxonForm; implementation +{$R *.lfm} + uses Math; -{ TWilcoxonFrm } +{ TWilcoxonForm } -procedure TWilcoxonFrm.ResetBtnClick(Sender: TObject); +procedure TWilcoxonForm.AdjustConstraints; +begin + inherited; + ParamsPanel.Constraints.MinHeight := Var2Out.Top + Var2Out.Height + + ButtonBevel.Height + CloseBtn.BorderSpacing.Top + CloseBtn.Height; + ParamsPanel.Constraints.MinWidth := 4*CloseBtn.Width + 3*CloseBtn.BorderSpacing.Left; +end; + + +procedure TWilcoxonForm.Compute; +var + A: DblDyneVec = nil; + b: DblDyneVec = nil; + d: DblDyneVec = nil; + r: DblDyneVec = nil; + index: IntDyneVec = nil; + ColNoSelected: IntDyneVec = nil; + negcnt: Integer = 0; + poscnt: Integer = 0; + zprob, numerator, denominator, z, negsum: double; + possum, t, sum, Avg: double; + M, N, i, j, itemp, col1, col2, NoSelected: integer; + labelone, labeltwo, cellstring: string; + lReport: TStrings; +begin + negsum := 0.0; + possum := 0.0; + NoSelected := 2; + + // Allocate memory + SetLength(ColNoSelected, NoVariables); + SetLength(A, NoCases); + SetLength(b, NoCases); + SetLength(d, NoCases); + SetLength(index, NoCases); + SetLength(r, NoCases); + + // Get column numbers and labels of variables selected + for i := 1 to NoVariables do + begin + cellstring := OS3MainFrm.DataGrid.Cells[i,0]; + if cellstring = Var1Edit.Text then + begin + ColNoSelected[0] := i; + labelone := cellstring; + end; + if cellstring = Var2Edit.Text then + begin + ColNoSelected[1] := i; + labeltwo := cellstring; + end; + end; + + // Get scores and differences + N := 0; + for i := 1 to NoCases do + begin + if (not GoodRecord(i,NoSelected,ColNoSelected)) then continue; + N := N + 1; + index[i-1] := N; + col1 := ColNoSelected[0]; + col2 := ColNoSelected[1]; + A[N-1] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col1,i])); + b[N-1] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col2,i])); + d[N-1] := A[N-1] - b[N-1]; + end; + + // Rank on absolute score differences + for i := 1 to N - 1 do + begin + for j := i + 1 to N do + begin + if (abs(d[i-1]) > abs(d[j-1])) then + begin + t := d[i-1]; + d[i-1] := d[j-1]; + d[j-1] := t; + t := A[i-1]; + A[i-1] := A[j-1]; + A[j-1] := t; + t := b[i-1]; + b[i-1] := b[j-1]; + b[j-1] := t; + itemp := index[i-1]; + index[i-1] := index[j-1]; + index[j-1] := itemp; + end; + end; + end; + + // Eliminate cases with 0 score differences + i := 1; + while (i <= N) do + begin + if (d[i-1] = 0.0) then // found a 0 score difference - move all up one + begin + if i < N then + begin + for j := i + 1 to N do + begin + d[j] := d[j-1]; + A[j] := A[j-1]; + b[j] := b[j-1]; + index[j] := index[j-1]; + end; + N := N - 1; + i := 1; + end + else begin + N := N - 1; + i := 1; + end; + end + else i := i + 1; + end; + + // Assign ranks + for i := 1 to N do r[i-1] := i; + + // Find matching differences and assign common rank + i := 1; + while (i < N) do + begin + M := 0; + sum := 0; + for j := i + 1 to N do + begin + if ( abs(d[j-1]) = abs(d[i-1]) ) then + begin + M := M + 1; + sum := sum + r[j-1]; + end; + end; + if (M > 0) then //matched differences found - assign average rank + begin + sum := sum + r[i-1]; // add the ith value too + Avg := sum / (M + 1); // count the ith value too + for j := i to (i + M) do r[j-1] := Avg; + i := i + M + 1; + end + else + i := i + 1; + end; + + // Assign sign of difference to ranks + for i := 1 to N do if (d[i-1] < 0.0) then r[i-1] := -r[i-1]; + + // Get sum of negative and positive difference ranks + for i := 1 to N do + begin + if (d[i-1] < 0.0) then + begin + negsum := negsum + abs(r[i-1]); + negcnt := negcnt + 1; + end + else + begin + possum := possum + abs(r[i-1]); + poscnt := poscnt + 1; + end; + end; + if (negsum < possum) then + t := negsum + else + t := possum; + numerator := t - ((N * (N + 1)) / 4.0); + denominator := sqrt((N * (N + 1) * (2 * N + 1)) / 24.0); + z := abs(numerator / denominator); + zprob := 1.0 - probz(z); + + // Now, display results + lReport := TStringList.Create; + try + lReport.Add('WILCONXON MATCHED-PAIRS SIGNED-RANKS TEST'); + lReport.Add('See pages 75-83 in S. Seigel: Nonparametric Statistics for the Social Sciences'); + lReport.Add(''); + lReport.Add('Ordered Cases with cases having 0 differences eliminated:'); + lReport.Add('Number of cases with absolute differences greater than 0: %d', [N]); + lReport.Add(''); + lReport.Add('CASE %10s %10s Difference Signed Rank', [labelone, labeltwo]); + for i := 1 to N do + lReport.Add('%3d %6.2f %6.2f %6.2f %6.2f', [index[i-1], A[i-1], b[i-1], d[i-1], r[i-1]]); + lReport.Add(''); + lReport.Add('Smaller sum of ranks (T): %8.2f', [t]); + lReport.Add('Approximately normal z for test statistic T: %8.4f', [z]); + lReport.Add('Probability (1-tailed) of greater z: %8.4f', [zprob]); + lReport.Add(''); + lReport.Add('NOTE: For N < 25 use tabled values for Wilcoxon Test'); + + FReportFrame.DisplayReport(lReport); + + finally + lReport.Free; + end; +end; + + +procedure TWilcoxonForm.Reset; var i: integer; begin + inherited; + Var1Edit.Text := ''; Var2Edit.Text := ''; VarList.Items.Clear; for i := 1 to NoVariables do VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); + UpdateBtnStates; end; -procedure TWilcoxonFrm.Var1InClick(Sender: TObject); + +procedure TWilcoxonForm.UpdateBtnStates; +begin + inherited; + + 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; + + +procedure TWilcoxonForm.Var1InClick(Sender: TObject); var index: integer; begin @@ -84,7 +291,8 @@ begin UpdateBtnStates; end; -procedure TWilcoxonFrm.Var1OutClick(Sender: TObject); + +procedure TWilcoxonForm.Var1OutClick(Sender: TObject); begin if Var1Edit.Text <> '' then begin @@ -94,7 +302,8 @@ begin UpdateBtnStates; end; -procedure TWilcoxonFrm.Var2InClick(Sender: TObject); + +procedure TWilcoxonForm.Var2InClick(Sender: TObject); var index: integer; begin @@ -107,7 +316,8 @@ begin UpdateBtnStates; end; -procedure TWilcoxonFrm.Var2OutClick(Sender: TObject); + +procedure TWilcoxonForm.Var2OutClick(Sender: TObject); begin if Var2Edit.Text <> '' then begin @@ -117,256 +327,52 @@ begin UpdateBtnStates; end; -procedure TWilcoxonFrm.VarListSelectionChange(Sender: TObject; User: boolean); + +function TWilcoxonForm.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 := Var1Edit; + exit; + end; + + Result := true; +end; + + +procedure TWilcoxonForm.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 TWilcoxonForm.VarListSelectionChange(Sender: TObject; User: boolean); begin UpdateBtnStates; end; -procedure TWilcoxonFrm.FormActivate(Sender: TObject); -var - w: Integer; -begin - if FAutoSized then - exit; - - w := MaxValue([HelpBtn.Width, ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]); - HelpBtn.Constraints.MinWidth := w; - ResetBtn.Constraints.MinWidth := w; - ComputeBtn.Constraints.MinWidth := w; - CloseBtn.Constraints.MinWidth := w; - - Constraints.MinWidth := Width; - Constraints.MinHeight := Height; - - FAutoSized := true; -end; - -procedure TWilcoxonFrm.FormCreate(Sender: TObject); -begin - Assert(OS3MainFrm <> nil); -end; - -procedure TWilcoxonFrm.FormShow(Sender: TObject); -begin - ResetBtnClick(self); -end; - -procedure TWilcoxonFrm.HelpBtnClick(Sender: TObject); -begin - if ContextHelpForm = nil then - Application.CreateForm(TContextHelpForm, ContextHelpForm); - ContextHelpForm.HelpMessage((Sender as TButton).tag); -end; - -procedure TWilcoxonFrm.ComputeBtnClick(Sender: TObject); -var - zprob, numerator, denominator, z, negsum : double; - possum, t, sum, Avg : double; - A, b, d, r : DblDyneVec; - M, N, i, j, itemp, col1, col2, NoSelected: integer; - index : IntdyneVec; - ColNoSelected : IntDyneVec; - labelone, labeltwo, cellstring: string; - lReport: TStrings; - negcnt: Integer = 0; - poscnt: Integer = 0; -begin - if Var1Edit.Text = '' then - begin - MessageDlg('Variable 1 not selected.', mtError, [mbOK], 0); - exit; - end; - - if Var2Edit.Text = '' then - begin - MessageDlg('Variable 2 not selected.', mtError, [mbOK], 0); - exit; - end; - - negsum := 0.0; - possum := 0.0; - NoSelected := 2; - - // Allocate memory - SetLength(ColNoSelected,NoVariables); - SetLength(A,NoCases); - SetLength(b,NoCases); - SetLength(d,NoCases); - SetLength(index,NoCases); - SetLength(r,NoCases); - - // Get column numbers and labels of variables selected - for i := 1 to NoVariables do - begin - cellstring := OS3MainFrm.DataGrid.Cells[i,0]; - if cellstring = Var1Edit.Text then - begin - ColNoSelected[0] := i; - labelone := cellstring; - end; - if cellstring = Var2Edit.Text then - begin - ColNoSelected[1] := i; - labeltwo := cellstring; - end; - end; - - // Get scores and differences - N := 0; - for i := 1 to NoCases do - begin - if (not GoodRecord(i,NoSelected,ColNoSelected)) then continue; - N := N + 1; - index[i-1] := N; - col1 := ColNoSelected[0]; - col2 := ColNoSelected[1]; - A[N-1] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col1,i])); - b[N-1] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col2,i])); - d[N-1] := A[N-1] - b[N-1]; - end; - - // Rank on absolute score differences - for i := 1 to N - 1 do - begin - for j := i + 1 to N do - begin - if (abs(d[i-1]) > abs(d[j-1])) then - begin - t := d[i-1]; - d[i-1] := d[j-1]; - d[j-1] := t; - t := A[i-1]; - A[i-1] := A[j-1]; - A[j-1] := t; - t := b[i-1]; - b[i-1] := b[j-1]; - b[j-1] := t; - itemp := index[i-1]; - index[i-1] := index[j-1]; - index[j-1] := itemp; - end; - end; - end; - - // Eliminate cases with 0 score differences - i := 1; - while (i <= N) do - begin - if (d[i-1] = 0.0) then // found a 0 score difference - move all up one - begin - if i < N then - begin - for j := i + 1 to N do - begin - d[j] := d[j-1]; - A[j] := A[j-1]; - b[j] := b[j-1]; - index[j] := index[j-1]; - end; - N := N - 1; - i := 1; - end - else begin - N := N - 1; - i := 1; - end; - end - else i := i + 1; - end; - - // Assign ranks - for i := 1 to N do r[i-1] := i; - - // Find matching differences and assign common rank - i := 1; - while (i < N) do - begin - M := 0; - sum := 0; - for j := i + 1 to N do - begin - if ( abs(d[j-1]) = abs(d[i-1]) ) then - begin - M := M + 1; - sum := sum + r[j-1]; - end; - end; - if (M > 0) then //matched differences found - assign average rank - begin - sum := sum + r[i-1]; // add the ith value too - Avg := sum / (M + 1); // count the ith value too - for j := i to (i + M) do r[j-1] := Avg; - i := i + M + 1; - end - else i := i + 1; - end; - - // Assign sign of difference to ranks - for i := 1 to N do if (d[i-1] < 0.0) then r[i-1] := -r[i-1]; - - // Get sum of negative and positive difference ranks - for i := 1 to N do - begin - if (d[i-1] < 0.0) then - begin - negsum := negsum + abs(r[i-1]); - negcnt := negcnt + 1; - end - else - begin - possum := possum + abs(r[i-1]); - poscnt := poscnt + 1; - end; - end; - if (negsum < possum) then t := negsum - else t := possum; - numerator := t - ((N * (N + 1)) / 4.0); - denominator := sqrt((N * (N + 1) * (2 * N + 1)) / 24.0); - z := abs(numerator / denominator); - zprob := 1.0 - probz(z); - - // Now, display results - lReport := TStringList.Create; - try - lReport.Add('WILCONXON MATCHED-PAIRS SIGNED-RANKS TEST'); - lReport.Add('See pages 75-83 in S. Seigel: Nonparametric Statistics for the Social Sciences'); - lReport.Add(''); - lReport.Add('Ordered Cases with cases having 0 differences eliminated:'); - lReport.Add('Number of cases with absolute differences greater than 0: %d', [N]); - lReport.Add('CASE %10s %10s Difference Signed Rank', [labelone, labeltwo]); - for i := 1 to N do - lReport.Add('%3d %6.2f %6.2f %6.2f %6.2f', [index[i-1], A[i-1], b[i-1], d[i-1], r[i-1]]); - lReport.Add(''); - lReport.Add('Smaller sum of ranks (T): %8.2f', [t]); - lReport.Add('Approximately normal z for test statistic T: %8.4f', [z]); - lReport.Add('Probability (1-tailed) of greater z: %8.4f', [zprob]); - lReport.Add(''); - lReport.Add('NOTE: For N < 25 use tabled values for Wilcoxon Test'); - - DisplayReport(lReport); - - finally - lReport.Free; - r := nil; - index := nil; - d := nil; - b := nil; - A := nil; - ColNoSelected := nil; - end; -end; - -procedure TWilcoxonFrm.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; - - -initialization - {$I wilcoxonunit.lrs} end. diff --git a/applications/lazstats/source/forms/mainunit.pas b/applications/lazstats/source/forms/mainunit.pas index d70e254d0..2c2148515 100644 --- a/applications/lazstats/source/forms/mainunit.pas +++ b/applications/lazstats/source/forms/mainunit.pas @@ -1808,17 +1808,17 @@ end; // Menu "Analysis" > "Nonparametric" > "Contingency Chi Square" procedure TOS3MainFrm.mnuAnalysisNonPar_ContingChiSqClick(Sender: TObject); begin - if ChiSqrFrm = nil then - Application.CreateForm(TChiSqrFrm, ChiSqrFrm); - ChiSqrFrm.ShowModal; + if ChiSqrForm = nil then + Application.CreateForm(TChiSqrForm, ChiSqrForm); + ChiSqrForm.Show; end; // Menu "Analysis" > "Nonparametric" > "Spearman Rank Correlation" procedure TOS3MainFrm.mnuAnalysisNonPar_SpearmanClick(Sender: TObject); begin - if SpearmanFrm = nil then - Application.CreateForm(TSpearmanFrm, SpearmanFrm); - SpearmanFrm.ShowModal; + if SpearmanForm = nil then + Application.CreateForm(TSpearmanForm, SpearmanForm); + SpearmanForm.Show; end; // Menu "Analysis" > "Nonparametric" > "Mann-Whitney U Test" @@ -1856,9 +1856,9 @@ end; // Menu "Analysis" > "Nonparametric" > "Matched Pairs Signed Ranks Test" procedure TOS3MainFrm.mnuAnalysisNonPar_WilcoxonClick(Sender: TObject); begin - if WilcoxonFrm = nil then - Application.CreateForm(TWilcoxonFrm, WilcoxonFrm); - WilcoxonFrm.ShowModal; + if WilcoxonForm = nil then + Application.CreateForm(TWilcoxonForm, WilcoxonForm); + WilcoxonForm.Show; end; // Menu "Analysis" > "Financial" > "Loan Amortization Schedule"