// File for testing: RunTest.laz, use VAR1 unit RunsTestUnit; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Buttons, ExtCtrls, MainUnit, Globals, BasicStatsReportFormUnit; type { TRunsTestForm } TRunsTestForm = class(TBasicStatsReportForm) Bevel1: TBevel; Bevel2: TBevel; InBtn: TBitBtn; OutBtn: TBitBtn; TestVarEdit: TEdit; Label1: TLabel; Label2: TLabel; VarList: TListBox; procedure InBtnClick(Sender: TObject); procedure OutBtnClick(Sender: TObject); procedure VarListDblClick(Sender: TObject); procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean); private protected procedure AdjustConstraints; override; procedure Compute; override; procedure UpdateBtnStates; override; public { public declarations } procedure Reset; override; end; var RunsTestForm: TRunsTestForm; implementation {$R *.lfm} uses Math, Utils, GridProcs, MatrixUnit; { TRunsTestForm } procedure TRunsTestForm.AdjustConstraints; begin inherited; ParamsPanel.Constraints.MinWidth := 4*CloseBtn.Width + 3*CloseBtn.BorderSpacing.Left; ParamsPanel.Constraints.MinHeight := OutBtn.Top + OutBtn.Height + ButtonBevel.Height + CloseBtn.BorderSpacing.Top + CloseBtn.Height; end; procedure TRunsTestForm.Compute; var a, i, col, N, N1, N2, NLess, Nmore, R: integer; mean, expMean, SD1, SD2, SD3, SD4, SD, z1, z2, z, t, p1, p: double; values: DblDyneVec = nil; lReport: TStrings; begin N := 0; N1 := 0; N2 := 0; Nless := 0; Nmore := 0; R := 1; Mean := 0.0; col := GetVariableIndex(OS3MainFrm.DataGrid, TestVarEdit.Text); if col = -1 then begin ErrorMsg('No variable was selected.'); exit; end; values := CollectVecValues(OS3MainFrm.DataGrid, col); N := Length(Values); if N <= 10 then begin ErrorMsg('Insufficient data. You must have at least 11 values.'); Values := nil; exit; end; mean := VecMean(values); // run through each value and compare with the mean for i := 0 to N-1 do begin // check and discard the ties with the mean if Mean <> Values[i] then begin // check if it is greater than the mean if Values[i] > mean then begin N1 := N1 + 1; a := i; while a > 0 do begin a := a - 1; if values[a] <> mean then break; end; if values[a] < mean then begin R := R + 1; nLess := nLess + 1; end; end else // check to see if it is less than the mean if Values[i] < Mean then begin N2 := N2 + 1; a := i; while a > 0 do begin a := a - 1; if values[a] <> mean then break; end; if values[a] > mean then begin R := R + 1; nMore := nMore + 1; end; end; end; end; // Compute the expected mean and variance of R expMean := 1.0 + ((2 * N1 * N2) / (N1 + N2)); // mean mu SD1 := 2 * N1 * N2 * (2 * N1 * N2 - N1 - N2); SD2 := power((N1 + N2), 2); SD3 := N1 + N2 - 1; SD4 := SD1 / (SD2 * SD3); // standard deviation "sigma" SD := sqrt(SD4); // calculating P Value z1 := (R - expMean) / SD; z2 := abs(z1); z := z2; if z > 0 then t := z else t := -z; p1 := power( (1 + t * (0.049867347 + t * (0.0211410061 + t * (0.0032776283 + t * (0.0000380036 + t * (0.0000488906 + t * (0.000005383))))))), -16 ); p := 1.0 - p1 / 2.0; if z > 0.0 then p := 1.0 - p else p := 1.0 - (1.0 - p); // show results lReport := TStringList.Create; try lReport.Add('RUNS TEST FOR RANDOMNESS'); lReport.Add(''); lReport.Add('Variable: %22s', [TestVarEdit.Text]); lReport.Add(''); lReport.Add('Mean: %12.3f', [mean]); lReport.Add('Standard deviation: %12.3f', [SD]); lReport.Add('N values > mean: %12d', [N1]); lReport.Add('N values < mean: %12d', [N2]); lReport.Add('Number of runs: %12d', [R]); lReport.Add('Test statistic: %12.3f', [z]); lReport.Add('Probability: %12.3f', [p]); lReport.Add(''); lReport.Add('Conclusion:'); // determine the conclusion if p < 0.01 then lReport.Add('Very strong evidence against randomness (trend or seasonality') else if (p < 0.05) and (p >= 0.01) then lReport.Add('Moderate evidence against randomness') else if (p < 0.10) and (p >= 0.05) then lReport.Add('Suggestive evidence against normality') else if p >= 0.10 then lReport.Add('Little or no real evidence against randomness') else lReport.Add('Strong evidence against randomness (trend or seasonality exists)');; FReportFrame.DisplayReport(lReport); finally lReport.Free; end; end; procedure TRunsTestForm.InBtnClick(Sender: TObject); var index: integer; begin index := VarList.ItemIndex; if (index > -1) and (TestVarEdit.Text = '') then begin TestVarEdit.Text := VarList.Items[index]; VarList.Items.Delete(index); UpdateBtnStates; end; end; procedure TRunsTestForm.OutBtnClick(Sender: TObject); begin if TestVarEdit.Text <> '' then begin VarList.Items.Add(TestVarEdit.Text); TestVarEdit.Text := ''; UpdateBtnStates; end; end; procedure TRunsTestForm.Reset; var i: integer; begin inherited; TestVarEdit.Clear; VarList.Clear; for i := 1 to NoVariables do VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); UpdateBtnStates; end; procedure TRunsTestForm.UpdateBtnStates; begin inherited; InBtn.Enabled := AnySelected(VarList) and (TestVarEdit.Text = ''); OutBtn.Enabled := TestVarEdit.Text <> ''; end; procedure TRunsTestForm.VarListDblClick(Sender: TObject); var index: Integer; begin index := VarList.ItemIndex; if (index > -1) then begin if (TestVarEdit.Text <> '') then VarList.Items.Add(TestVarEdit.Text); TestVarEdit.Text := VarList.Items[index]; VarList.Items.Delete(index); UpdateBtnStates; end; end; procedure TRunsTestForm.VarListSelectionChange(Sender: TObject; User: boolean); begin UpdateBtnStates; end; end.