From 93146b63ea0591508aa627e592acb6b1a8491f40 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Fri, 10 Apr 2020 21:56:25 +0000 Subject: [PATCH] LazStats: Refactor HierarchUnit. Some clean-up. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7369 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../lazstats/docs/HelpNDoc/LazStats.hnd | Bin 5869568 -> 5935104 bytes .../forms/analysis/comparisons/glmunit.pas | 16 +- .../analysis/multivariate/discrimunit.pas | 24 +- .../analysis/multivariate/factorunit.pas | 37 +- .../analysis/multivariate/hierarchunit.lfm | 75 +- .../analysis/multivariate/hierarchunit.pas | 738 +++++++++--------- .../forms/analysis/multivariate/pathunit.pas | 8 +- .../nonparametric/kaplanmeierunit.pas | 3 +- .../lazstats/source/units/dataprocs.pas | 1 - 9 files changed, 434 insertions(+), 468 deletions(-) diff --git a/applications/lazstats/docs/HelpNDoc/LazStats.hnd b/applications/lazstats/docs/HelpNDoc/LazStats.hnd index 0baf4995fdd06a6954971802bbee697f67aa1492..92ae98449e132a42ad9eb816656bd5842a412e0c 100644 GIT binary patch delta 47293 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 L(G1Wd1?B$-zKQ)X delta 2628 zcmZvddsGzn702iI`_1gm?9KxS(SRVc!?M-|6(68LM11htbpeZ_=)quZ)QTF+qdsZ` zH91=!L5YuhOiMu;L(+@G$_!>R=Vme>RpN23oV&q^#cB=h&EF*3B~^)`=afg}lvqzn$xvs8 zt(zT?PKb6bSNSaH^rCEe!h$-LiUP~ zeKBO$wo{$wE+jDMZt@tAnaynQ(iIu^ejZw1_`ZtLpTY0PqjXV!OXOT=A^eVvf&a$9 z&Mh8;a{q#AtfD9J4X^t!=q#KWhd~RQRUMY+q3%~XSmtIQ{#)2&W&c+=ItCxsWwS)+ zoLdq{x%c4GX!Pi~hoW-BPE6^J721A84cXt^u#{GVJQfeSfSt7ta!z7c!b+H7^1NP1uf!0hJIgsYbPeNm=)y)?{&t7MAf?b5U@Dgh!$1wN{%~{% zud^YzR{KaY*kCl)*N-(wGA#7tstdcz2BPzC_b_q*%+Fy7&|JV0EVb7A=<|a9UsUT4 z2mP3yn*|7T{)g(MAN+uR!4vYla1K2QupT{7>1P7$euTeO(Rj3Klkt2Ps+E7>F@!iA z8wsJ;f*I)3iwphwVb6m8x9k=!TX>Z4MkE|D&E$+}LGc}pdl)$=M zV5ae&(0wrVbiPdhx!F|~q***7AU4E~h$hXF%JvXymfw|5$s~JolH!G8n3QXC7PwIm!HV5iVw}y zHhHf=E}6Hk$t4UvoLBNj@c2#HJbqIdl^Pkxt>CmZTDba-8n67BzQ`X@hCsBg4&>Qc zdI_h-aCoaFNiC@rm0JUC*3NdAz?^35`jE}L?X{3y^!9> zbLL5R)bpou`cTTLAa$sHl_n)wJ|Jg1KXP1f7SrE|QS2(Kpw!-IPqgi|jTBA@h5UKP z48DwhtF6|;r2Eox$u4dnYe@v=R%mYRjCyDn$P~SG9p^huWx4QzMl#5ZxIwnY5afoiSMiynJjf%i#mivfFK# zG2g~?D8^uJ3&$t2YpkA4VG;B+w?#Xky{sjv*VP8KRDDMIc(XTl98ce%nVT2HzD(}y zYmY4>uswA^P4G00MfxIfh;E*yu9P|_zA{9a%_+0BH%+<0^@9ZUuO(|xaU|+l&|gbd z%|1<~iHtw)5bVKr& zR4!CnA|0e&RqNErYMAm5WhL3BWPs7&>Ds6lll^eKRw1 zBKak!eWC5wYPES94h6bEGa$OnTWKR}#Es$t*wp4V&=#f(Y3BYm?=ebgF&sVNcA0fo zydUDd{ari{EoD@IO!;lmt6&a3fqmV3QG%^Mmi;P3EksKr!$um2zVittP?hni6EPSzR+_WjGbqL0D^2UpTbG<%i0! zj8tej;dYv{{^)ww_J3~3GEuNfUIv3ca_eSIb;(c)cUnu=nOAq0#whO{nR51jRk=;T diff --git a/applications/lazstats/source/forms/analysis/comparisons/glmunit.pas b/applications/lazstats/source/forms/analysis/comparisons/glmunit.pas index de48b6a10..f8a3ecc85 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/glmunit.pas +++ b/applications/lazstats/source/forms/analysis/comparisons/glmunit.pas @@ -1541,13 +1541,11 @@ var block, i, j, k, NEntered, index, noblocks, priorentered : integer; cellstring : string; labelstr : string; - outline : string; R, R2Increment, SSx, sum, constant, FullR2 : double; - df1, df2, F, FProbF, StdErrB,OldDF1, PredSS, PredMS : double; + df1, df2, F, FProbF, StdErrB, PredSS, PredMS : double; SSt, VarEst, SSres, StdErrEst, AdjR2 : double; begin NEntered := 0; - OldDF1 := 0.0; priorentered := 0; OldR2 := 0; @@ -2272,20 +2270,18 @@ end; procedure TGLMFrm.ModelIIIAnalysis(AReport: TStrings); var - block, i, j, NEntered, index, noblocks, priorentered : integer; + block, i, j, NEntered, index, noblocks: integer; cellstring : string; labelstr : string; - outline, effstr : string; + effstr : string; R, SSx, sum, constant: double; - df1, df2, F, FProbF, StdErrB, OldDF1: double; + df1, df2, F, FProbF, StdErrB: double; SSt, VarEst, SSres, StdErrEst, AdjR2 : double; dfbetween, dferrbetween, dfwithin, dferrwithin : double; ssbetween, sserrbetween, mserrbetween, sswithin, sserrwithin, mserrwithin : double; betweenblock : integer; totalss, totaldf : double; begin - OldDF1 := 0.0; - priorentered := 0; OldR2 := 0; ColSelected[0] := ReptDepPos[0]; Labels[0] := GenLabels[1]; @@ -2979,7 +2975,7 @@ var s, m, n, df1, df2, q, w, pcnt_extracted, trace : double; minroot, critical_prob, Lambda, Pillia : double; chisqr, HLTrace, chiprob, ftestprob, Roys, f, Hroot : double; - raa, rbb, rab, rba, bigmat, prod, first_prod, second_prod : DblDyneMat; + raa, rbb, rab, rba, bigmat, first_prod, second_prod : DblDyneMat; char_equation, raainv, rbbinv, eigenvectors, norm_a, norm_b : DblDyneMat; raw_a, raw_b, a_cors, b_cors, eigentrans, theta, tempmat : DblDyneMat; mean, variance, stddev, roots, root_chi, chi_prob, pv_a, pv_b : DblDyneVec; @@ -3016,7 +3012,6 @@ begin SetLength(rab,NLeft+1,NRight+1); SetLength(rba,NRight+1,NLeft+1); SetLength(bigmat,novars+1,novars+1); - SetLength(prod,novars+1,novars+1); SetLength(first_prod,novars+1,novars+1); SetLength(second_prod,novars+1,novars+1); SetLength(char_equation,novars+1,novars+1); @@ -3401,7 +3396,6 @@ cleanup: char_equation := nil; second_prod := nil; first_prod := nil; - prod := nil; bigmat := nil; rba := nil; rab := nil; diff --git a/applications/lazstats/source/forms/analysis/multivariate/discrimunit.pas b/applications/lazstats/source/forms/analysis/multivariate/discrimunit.pas index 78264e6b9..86711ca55 100644 --- a/applications/lazstats/source/forms/analysis/multivariate/discrimunit.pas +++ b/applications/lazstats/source/forms/analysis/multivariate/discrimunit.pas @@ -169,17 +169,17 @@ var Title : string; GrpVar, NoGrps, nowithin, TotalCases, value, grpno : integer; ColNoSelected : IntDyneVec; - CaseNo, NoInGrp : IntDyneVec; + NoInGrp : IntDyneVec; VarLabels, ColLabels, GrpNos : StrDyneVec; X, Y, GroupSS, ErrorSS, GroupMS, ErrorMS, TotalSS, num, s, v2, den : double; Lambda, ChiSquare, Pillia, TotChi, p, Rc, chi, chiprob, m, L2, F, Fprob : double; DFGroup, DFError, DFTotal, Fratio, prob, minroot, trace, pcnttrace : double; probchi : double; - WithinMat, WithinInv, WinvB, v, PooledW, TotalMat, BetweenMat : DblDyneMat; + WithinMat, WithinInv, WinvB, PooledW, TotalMat, BetweenMat : DblDyneMat; EigenVectors, EigenTrans, TempMat, Theta, DiagMat, CoefMat : DblDyneMat; RawCMat, GrpMeans, GrpSDevs, Centroids, Structure : DblDyneMat; Constants, ScoreVar, Roots, Pcnts, TotalMeans, TotalVariances : DblDyneVec; - TotalStdDevs, WithinMeans, WithinVariances, WithinStdDevs, w : DblDyneVec; + TotalStdDevs, WithinMeans, WithinVariances, WithinStdDevs: DblDyneVec; errorcode : boolean = false; lReport: TStrings; begin @@ -194,6 +194,13 @@ begin exit; end; + if ClassSizeGroup.ItemIndex = -1 then + begin + ClassSizeGroup.SetFocus; + MessageDlg('"Classify Using" is not specified.', mtError, [mbOk], 0); + exit; + end; + TotalCases := 0; lReport := TStringList.Create; @@ -208,7 +215,6 @@ begin SetLength(ColNoSelected,NoVariables); SetLength(VarLabels,NoVariables); SetLength(ColLabels,NoVariables); - SetLength(CaseNo,NoVariables); // Get items selected for i := 1 to NoSelected - 1 do @@ -233,7 +239,6 @@ begin SetLength(WithinMat,NoVariables,NoVariables); SetLength(WithinInv,NoVariables,NoVariables); SetLength(WinvB,NoVariables,NoVariables); - SetLength(v,NoVariables,NoVariables); SetLength(PooledW,NoVariables,NoVariables); SetLength(TotalMat,NoVariables,NoVariables); SetLength(BetweenMat,NoVariables,NoVariables); @@ -255,7 +260,6 @@ begin SetLength(WithinMeans,NoVariables); SetLength(WithinVariances,NoVariables); SetLength(WithinStdDevs,NoVariables); - SetLength(w,NoVariables); // Initialize arrays for i := 0 to NoSelected-1 do @@ -782,7 +786,6 @@ begin Centroids := nil; GrpSDevs := nil; GrpMeans := nil; - w := nil; WithinStdDevs := nil; WithinVariances := nil; WithinMeans := nil; @@ -804,11 +807,9 @@ begin BetweenMat := nil; TotalMat := nil; PooledW := nil; - v := nil; WinvB := nil; WithinInv := nil; WithinMat := nil; - CaseNo := nil; ColLabels := nil; VarLabels := nil; end; @@ -984,7 +985,6 @@ procedure TDiscrimFrm.Classify(Sender: TObject; PooledW: DblDyneMat; VarLabels: StrDyneVec; AReport: TStrings); var i, j, k, grp : integer; - outline : string; Constant, T : DblDyneVec; S : double; Coeff, WithinInv : DblDyneMat; @@ -1041,7 +1041,7 @@ var i, j, k, grp, j1, InGrp, Largest, SecdLarge, oldcolcnt, linecount : integer; numberstr, prompt, outline, cellname : string; Table : IntDyneMat; - ProdVec, Dev, D2, Density, ProbGrp, Apriori, Discrim : DblDyneVec; + ProdVec, Dev, D2, ProbGrp, Apriori, Discrim : DblDyneVec; SumD2, Determinant, LargestProb, SecdProb, X : double; RowLabels, ColLabels : StrDyneVec; WithinInv : DblDyneMat; @@ -1054,7 +1054,6 @@ begin SetLength(ProdVec,NoSelected); SetLength(Dev,NoSelected); SetLength(D2,NoGrps); - SetLength(Density,NoGrps); SetLength(ProbGrp,NoGrps); SetLength(Apriori,NoGrps); SetLength(Discrim,noroots); @@ -1253,7 +1252,6 @@ begin Discrim := nil; Apriori := nil; ProbGrp := nil; - Density := nil; D2 := nil; Dev := nil; ProdVec := nil; diff --git a/applications/lazstats/source/forms/analysis/multivariate/factorunit.pas b/applications/lazstats/source/forms/analysis/multivariate/factorunit.pas index c96f3cf8e..32d76c1a1 100644 --- a/applications/lazstats/source/forms/analysis/multivariate/factorunit.pas +++ b/applications/lazstats/source/forms/analysis/multivariate/factorunit.pas @@ -138,11 +138,11 @@ procedure TFactorFrm.ComputeBtnClick(Sender: TObject); label again; var i, j, k, L, Nroots, noiterations, NoSelected, factorchoice : integer; - maxiters, prtopts, maxnoroots, count : integer; - TempMat, V, corrmat, ainverse, Loadings : DblDyneMat; - Eigenvector, pcnttrace, b, communality, xvector, yvector, d2 : DblDyneVec; - means, variances, stddevs, W : DblDyneVec; - MaxRoot, criterion, Difference, minroot, maxk, trace : double; + maxiters, maxnoroots, count : integer; + TempMat, corrmat, ainverse, Loadings : DblDyneMat; + Eigenvector, b, communality, xvector, yvector, d2 : DblDyneVec; + means, variances, stddevs: DblDyneVec; + criterion, Difference, minroot, trace : double; cellstring, outline, xtitle, ytitle : string; ColNoSelected : IntDyneVec; RowLabels, ColLabels : StrDyneVec; @@ -161,25 +161,12 @@ begin exit; end; - MaxRoot := 0.0; NoIterations := 0; MaxNoRoots := 0; - PrtOpts := 0; criterion := 0.0001; //Convergence of communality estimates - //factorchoice := 1; // assume principal component factorChoice := TypeGroup.ItemIndex + 1; - { - if (TypeGroup.ItemIndex = 1) then factorchoice := 2; - if (TypeGroup.ItemIndex = 2) then factorchoice := 3; - if (TypeGroup.ItemIndex = 3) then factorchoice := 4; - if (TypeGroup.ItemIndex = 4) then factorchoice := 5; - if (TypeGroup.ItemIndex = 5) then factorchoice := 6; - if (TypeGroup.ItemIndex = 6) then factorchoice := 7; - } - if RMatBtn.Checked then prtopts := 3; // wp: why changed in next line? - if RMatBtn.Checked then prtopts := 2; - if RMatBtn.Checked and DescBtn.Checked then prtopts := 1; + maxiters := StrToInt(MaxItersEdit.Text); if (MaxFactorsEdit.Text <> '') then MaxNoRoots := StrToInt(MaxFactorsEdit.Text); @@ -203,12 +190,9 @@ begin SetLength(corrmat, NoVariables + 1, NoVariables + 1); SetLength(TempMat, NoVariables, NoVariables); SetLength(ainverse, NoVariables, NoVariables); - SetLength(V, NoVariables, NoVariables); - SetLength(W, NoVariables); SetLength(Loadings, NoVariables, NoVariables); SetLength(Eigenvector, NoVariables); SetLength(communality, NoVariables); - SetLength(pcnttrace, NoVariables); SetLength(b, NoVariables); SetLength(d2, NoVariables); SetLength(xvector, NoVariables); @@ -290,7 +274,6 @@ begin MatSave(corrmat, NoSelected, NoSelected, means, stddevs, count, RowLabels, ColLabels, filename); end; end; - maxk := k; Nroots := k; //not a principal component analysis @@ -688,12 +671,9 @@ again: xvector := nil; d2 := nil; b := nil; - pcnttrace := nil; communality := nil; Eigenvector := nil; Loadings := nil; - W := nil; - V := nil; ainverse := nil; TempMat := nil; corrmat := nil; @@ -1130,7 +1110,6 @@ var ee, p, sum : double; A, C, d, v, trans : DblDyneMat; e, f, g, means, stddevs : DblDyneVec; - outline : string; Title : string; ColALabels : StrDyneVec ; filename : string; @@ -1382,7 +1361,7 @@ procedure TFactorFrm.QuartiMax(const v: DblDyneMat; n1, n2: integer; AReport: TStrings); var i, j, M, N, minuscount, NoIters : integer; - A, b, C : DblDyneVec; + A, b: DblDyneVec; High_Factor : IntDyneVec; c4, s1, Q, NewQ, TotalPercent, t : double; theta, tan4theta, ssqrp, ssqrj, prodjp, numerator, denominator : double; @@ -1391,7 +1370,6 @@ var begin SetLength(A,NoVariables); SetLength(b,NoVariables); - SetLength(C,NoVariables); SetLength(High_Factor,NoVariables); NoIters := 0; @@ -1554,7 +1532,6 @@ begin AReport.Add(''); High_Factor := nil; - C := nil; b := nil; A := nil; end; diff --git a/applications/lazstats/source/forms/analysis/multivariate/hierarchunit.lfm b/applications/lazstats/source/forms/analysis/multivariate/hierarchunit.lfm index 4eae03343..80ca80c85 100644 --- a/applications/lazstats/source/forms/analysis/multivariate/hierarchunit.lfm +++ b/applications/lazstats/source/forms/analysis/multivariate/hierarchunit.lfm @@ -1,11 +1,11 @@ object HierarchFrm: THierarchFrm Left = 415 - Height = 302 + Height = 319 Top = 211 Width = 442 AutoSize = True Caption = 'Hierarchical Cluster Analysis' - ClientHeight = 302 + ClientHeight = 319 ClientWidth = 442 OnActivate = FormActivate OnCreate = FormCreate @@ -42,7 +42,7 @@ object HierarchFrm: THierarchFrm AnchorSideRight.Control = PredIn AnchorSideBottom.Control = Bevel1 Left = 8 - Height = 228 + Height = 245 Top = 25 Width = 176 Anchors = [akTop, akLeft, akRight, akBottom] @@ -51,6 +51,7 @@ object HierarchFrm: THierarchFrm BorderSpacing.Right = 8 ItemHeight = 0 MultiSelect = True + OnSelectionChange = VarListSelectionChange TabOrder = 0 end object PredIn: TBitBtn @@ -91,7 +92,7 @@ object HierarchFrm: THierarchFrm AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = GroupBox1 Left = 228 - Height = 45 + Height = 62 Top = 25 Width = 206 Anchors = [akTop, akLeft, akRight, akBottom] @@ -99,6 +100,8 @@ object HierarchFrm: THierarchFrm BorderSpacing.Right = 8 BorderSpacing.Bottom = 8 ItemHeight = 0 + MultiSelect = True + OnSelectionChange = VarListSelectionChange TabOrder = 3 end object GroupBox1: TGroupBox @@ -109,7 +112,7 @@ object HierarchFrm: THierarchFrm AnchorSideBottom.Control = Bevel1 Left = 228 Height = 175 - Top = 78 + Top = 95 Width = 206 Anchors = [akRight, akBottom] AutoSize = True @@ -225,86 +228,68 @@ object HierarchFrm: THierarchFrm end end object ResetBtn: TButton - AnchorSideRight.Control = CancelBtn + AnchorSideRight.Control = ComputeBtn AnchorSideBottom.Control = Owner AnchorSideBottom.Side = asrBottom - Left = 141 + Left = 233 Height = 25 - Top = 269 + Top = 286 Width = 54 Anchors = [akRight, akBottom] AutoSize = True - BorderSpacing.Left = 12 + BorderSpacing.Left = 8 BorderSpacing.Top = 8 - BorderSpacing.Right = 12 + BorderSpacing.Right = 8 BorderSpacing.Bottom = 8 Caption = 'Reset' OnClick = ResetBtnClick TabOrder = 5 end - object CancelBtn: TButton - AnchorSideRight.Control = ComputeBtn - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 207 - Height = 25 - Top = 269 - Width = 62 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 12 - BorderSpacing.Top = 8 - BorderSpacing.Right = 12 - BorderSpacing.Bottom = 8 - Caption = 'Cancel' - ModalResult = 2 - TabOrder = 6 - end object ComputeBtn: TButton - AnchorSideRight.Control = ReturnBtn + AnchorSideRight.Control = CloseBtn AnchorSideBottom.Control = Owner AnchorSideBottom.Side = asrBottom - Left = 281 + Left = 295 Height = 25 - Top = 269 + Top = 286 Width = 76 Anchors = [akRight, akBottom] AutoSize = True - BorderSpacing.Left = 12 + BorderSpacing.Left = 8 BorderSpacing.Top = 8 - BorderSpacing.Right = 12 + BorderSpacing.Right = 8 BorderSpacing.Bottom = 8 Caption = 'Compute' OnClick = ComputeBtnClick - TabOrder = 7 + TabOrder = 6 end - object ReturnBtn: TButton + object CloseBtn: TButton AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = Owner AnchorSideBottom.Side = asrBottom - Left = 369 + Left = 379 Height = 25 - Top = 269 - Width = 61 + Top = 286 + Width = 55 Anchors = [akRight, akBottom] AutoSize = True - BorderSpacing.Left = 12 + BorderSpacing.Left = 8 BorderSpacing.Top = 8 - BorderSpacing.Right = 12 + BorderSpacing.Right = 8 BorderSpacing.Bottom = 8 - Caption = 'Return' - ModalResult = 1 - TabOrder = 8 + Caption = 'Close' + ModalResult = 11 + TabOrder = 7 end object Bevel1: TBevel AnchorSideLeft.Control = Owner AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = ReturnBtn + AnchorSideBottom.Control = CloseBtn Left = 0 Height = 8 - Top = 253 + Top = 270 Width = 442 Anchors = [akLeft, akRight, akBottom] Shape = bsBottomLine diff --git a/applications/lazstats/source/forms/analysis/multivariate/hierarchunit.pas b/applications/lazstats/source/forms/analysis/multivariate/hierarchunit.pas index 677587c88..17b0836b2 100644 --- a/applications/lazstats/source/forms/analysis/multivariate/hierarchunit.pas +++ b/applications/lazstats/source/forms/analysis/multivariate/hierarchunit.pas @@ -1,3 +1,5 @@ +// Sample file for testing: cansas.laz, use all variiables. + unit HierarchUnit; {$mode objfpc}{$H+} @@ -16,9 +18,8 @@ type THierarchFrm = class(TForm) Bevel1: TBevel; ResetBtn: TButton; - CancelBtn: TButton; ComputeBtn: TButton; - ReturnBtn: TButton; + CloseBtn: TButton; MaxGrps: TEdit; STDChk: TCheckBox; ReplaceChk: TCheckBox; @@ -41,9 +42,11 @@ type procedure PredInClick(Sender: TObject); procedure PredOutClick(Sender: TObject); procedure ResetBtnClick(Sender: TObject); + procedure VarListSelectionChange(Sender: TObject; User: boolean); private { private declarations } FAutoSized: Boolean; + procedure UpdateBtnStates; public { public declarations } end; @@ -54,26 +57,26 @@ var implementation uses - Math; + Math, Utils; { THierarchFrm } procedure THierarchFrm.ResetBtnClick(Sender: TObject); -VAR i : integer; +var + i: integer; begin - VarList.Clear; - PredList.Clear; - PredOut.Enabled := false; - PredIn.Enabled := true; - StdChk.Checked := false; - ReplaceChk.Checked := false; - StatsChk.Checked := false; - PlotChk.Checked := false; - MaxGrpsChk.Checked := false; - VarChk.Checked := false; - MaxGrps.Text := ''; - for i := 1 to NoVariables do - VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); + VarList.Clear; + PredList.Clear; + StdChk.Checked := false; + ReplaceChk.Checked := false; + StatsChk.Checked := false; + PlotChk.Checked := false; + MaxGrpsChk.Checked := false; + VarChk.Checked := false; + MaxGrps.Text := ''; + for i := 1 to NoVariables do + VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); + UpdateBtnStates; end; procedure THierarchFrm.FormActivate(Sender: TObject); @@ -83,11 +86,10 @@ begin if FAutoSized then exit; - w := MaxValue([ResetBtn.Width, CancelBtn.Width, ComputeBtn.Width, ReturnBtn.Width]); + w := MaxValue([ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]); ResetBtn.Constraints.MinWidth := w; - CancelBtn.Constraints.MinWidth := w; ComputeBtn.Constraints.MinWidth := w; - ReturnBtn.Constraints.MinWidth := w; + CloseBtn.Constraints.MinWidth := w; VarList.Constraints.MinWidth := PredList.Width; Constraints.MinWidth := Width; @@ -99,8 +101,8 @@ end; procedure THierarchFrm.FormCreate(Sender: TObject); begin Assert(OS3MainFrm <> nil); - if OutputFrm = nil then - Application.CreateForm(TOutputFrm, OutputFrm); + if GraphFrm = nil then + Application.CreateForm(TGraphFrm, GraphFrm); end; procedure THierarchFrm.FormShow(Sender: TObject); @@ -111,84 +113,101 @@ end; procedure THierarchFrm.ComputeBtnClick(Sender: TObject); label next1; var - varlabels, rowlabels : StrDyneVec; - outline, cellstring : string; - i, j, k, k1, k3, L, w3, n3, n4, n5, M, col, count: integer; - GrpCnt, Nrows, Ncols, NoSelected, linecount : integer; - w2, k4, k5, L1 : IntDyneVec; - ColSelected : IntDyneVec; - X, Y, d1, x1, MaxError : double; - W, XAxis, YAxis, means, variances, stddevs : DblDyneVec; - Distance : DblDyneMat; + varlabels, rowlabels : StrDyneVec; + cellstring : string; + i, j, k, k1, k3, L, w3, n3, n4, n5, M, col, count: integer; + GrpCnt, Nrows, Ncols, NoSelected: integer; + w2, k4, k5, L1 : IntDyneVec; + ColSelected : IntDyneVec; + X, Y, d1, x1, MaxError : double; + W, XAxis, YAxis, means, variances, stddevs : DblDyneVec; + Distance : DblDyneMat; + lReport: TStrings; begin - MaxError := 0.0; - GrpCnt := 0; - NoSelected := PredList.Items.Count; - if VarChk.Checked = false then - begin - SetLength(w2,NoCases); - SetLength(k4,NoCases); - SetLength(k5,NoCases); - SetLength(L1,NoCases); - SetLength(W,NoSelected); - SetLength(XAxis,NoCases); - SetLength(YAxis,NoCases); - SetLength(means,NoSelected); - SetLength(variances,NoSelected); - SetLength(stddevs,NoSelected); - SetLength(Distance,NoCases,NoCases); - SetLength(varlabels,NoSelected); - SetLength(rowlabels,NoCases); - SetLength(ColSelected,NoSelected); - Ncols := NoSelected; - Nrows := NoCases; - for i := 0 to Ncols - 1 do - begin - cellstring := PredList.Items.Strings[i]; - for j := 1 to NoVariables do - begin - if (cellstring = OS3MainFrm.DataGrid.Cells[j,0]) then - begin - varlabels[i] := cellstring; - ColSelected[i] := j; - end; - end; - end; - for i := 0 to NoCases-1 do rowlabels[i] := IntToStr(i); - end - else begin - SetLength(w2,NoSelected); - SetLength(k4,NoSelected); - SetLength(k5,NoSelected); - SetLength(L1,NoSelected); - SetLength(W,NoCases); - SetLength(XAxis,NoSelected); - SetLength(YAxis,NoSelected); - SetLength(means,NoCases); - SetLength(variances,NoCases); - SetLength(stddevs,NoCases); - SetLength(Distance,NoSelected,NoCases); - SetLength(varlabels,NoCases); - SetLength(rowlabels,NoSelected); - SetLength(ColSelected,NoSelected); - Ncols := NoCases; - Nrows := NoSelected; - //Get labels of selected variables - for i := 0 to Nrows - 1 do - begin - cellstring := PredList.Items.Strings[i]; - for j := 1 to NoVariables do - begin - if (cellstring = OS3MainFrm.DataGrid.Cells[j,0]) then - begin - ColSelected[i] := j; - rowlabels[i] := cellstring; - end; - end; - end; - for i := 0 to NoCases-1 do varlabels[i] := IntToStr(i); - end; - if MembersChk.Checked then k3 := 1 else k3 := 0; + if MaxGrpsChk.Checked then + begin + if MaxGrps.Text = '' then + begin + MessageDlg('Maximum number of groups not specified.', mtError, [mbOK], 0); + exit; + end; + if not TryStrToInt(MaxGrps.Text, k1) or (k1 < 1) then + begin + Messagedlg('No valid number of groups given.', mtError, [mbOK], 0); + exit; + end; + end; + + MaxError := 0.0; + GrpCnt := 0; + NoSelected := PredList.Items.Count; + if not VarChk.Checked then + begin + SetLength(w2,NoCases); + SetLength(k4,NoCases); + SetLength(k5,NoCases); + SetLength(L1,NoCases); + SetLength(W,NoSelected); + SetLength(XAxis,NoCases); + SetLength(YAxis,NoCases); + SetLength(means,NoSelected); + SetLength(variances,NoSelected); + SetLength(stddevs,NoSelected); + SetLength(Distance,NoCases,NoCases); + SetLength(varlabels,NoSelected); + SetLength(rowlabels,NoCases); + SetLength(ColSelected,NoSelected); + Ncols := NoSelected; + Nrows := NoCases; + for i := 0 to Ncols - 1 do + begin + cellstring := PredList.Items.Strings[i]; + for j := 1 to NoVariables do + begin + if (cellstring = OS3MainFrm.DataGrid.Cells[j,0]) then + begin + varlabels[i] := cellstring; + ColSelected[i] := j; + end; + end; + end; + for i := 0 to NoCases-1 do rowlabels[i] := IntToStr(i); + end else + begin + SetLength(w2,NoSelected); + SetLength(k4,NoSelected); + SetLength(k5,NoSelected); + SetLength(L1,NoSelected); + SetLength(W,NoCases); + SetLength(XAxis,NoSelected); + SetLength(YAxis,NoSelected); + SetLength(means,NoCases); + SetLength(variances,NoCases); + SetLength(stddevs,NoCases); + SetLength(Distance,NoSelected,NoCases); + SetLength(varlabels,NoCases); + SetLength(rowlabels,NoSelected); + SetLength(ColSelected,NoSelected); + Ncols := NoCases; + Nrows := NoSelected; + //Get labels of selected variables + for i := 0 to Nrows - 1 do + begin + cellstring := PredList.Items.Strings[i]; + for j := 1 to NoVariables do + begin + if (cellstring = OS3MainFrm.DataGrid.Cells[j,0]) then + begin + ColSelected[i] := j; + rowlabels[i] := cellstring; + end; + end; + end; + for i := 0 to NoCases-1 do + varlabels[i] := IntToStr(i); + end; + + if MembersChk.Checked then k3 := 1 else k3 := 0; for j := 0 to Ncols-1 do begin @@ -199,45 +218,45 @@ begin if VarChk.Checked = false then begin - // Get labels of rows + // Get labels of rows // for i := 1 to Nrows do rowlabels[i-1] := MainFrm.Grid.Cells[0,i]; - // Get data into the distance matrix - count := 0; - for i := 1 to Nrows do - begin - if (not GoodRecord(i,NoSelected,ColSelected)) then continue; - count := count + 1; - for j := 1 to Ncols do - begin - col := ColSelected[j-1]; - X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col,i])); - means[j-1] := means[j-1] + X; - variances[j-1] := variances[j-1] + (X * X); - Distance[i-1,j-1] := X; - end; - end; - end - else begin // cluster variables - // Get labels of columns + // Get data into the distance matrix + count := 0; + for i := 1 to Nrows do + begin + if (not GoodRecord(i,NoSelected,ColSelected)) then continue; + count := count + 1; + for j := 1 to Ncols do + begin + col := ColSelected[j-1]; + X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col,i])); + means[j-1] := means[j-1] + X; + variances[j-1] := variances[j-1] + (X * X); + Distance[i-1,j-1] := X; + end; + end; + end else + begin // cluster variables + // Get labels of columns // for i := 1 to Nrows do rowlabels[i-1] := MainFrm.Grid.Cells[i,0]; - // Get data into the distance matrix - count := 0; - for i := 1 to Nrows do // actually grid column in this case - begin -// if (not GoodRecord(i,NoSelected,ColSelected)) then continue; - count := count + 1; - for j := 1 to Ncols do // actually grid rows in this case - begin -// if (not GoodRecord(j,NoSelected,ColSelected)) then continue; - col := ColSelected[i-1]; - X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col,j])); - means[j-1] := means[j-1] + X; - variances[j-1] := variances[j-1] + (X * X); - Distance[i-1,j-1] := X; - end; - end; + // Get data into the distance matrix + count := 0; + for i := 1 to Nrows do // actually grid column in this case + begin +// if (not GoodRecord(i,NoSelected,ColSelected)) then continue; + count := count + 1; + for j := 1 to Ncols do // actually grid rows in this case + begin +// if (not GoodRecord(j,NoSelected,ColSelected)) then continue; + col := ColSelected[i-1]; + X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col,j])); + means[j-1] := means[j-1] + X; + variances[j-1] := variances[j-1] + (X * X); + Distance[i-1,j-1] := X; + end; + end; end; // Calculate means and standard deviations of variables @@ -250,266 +269,263 @@ begin end; // Ready the output form - OutputFrm.RichEdit.Clear; - OutputFrm.RichEdit.Lines.Add('Hierarchical Cluster Analysis'); - OutputFrm.RichEdit.Lines.Add(''); - outline := format('Number of objects to cluster := %d on %d variables.', - [Nrows, Ncols]); - OutputFrm.RichEdit.Lines.Add(outline); - linecount := 3; - if (StatsChk.Checked) then - begin - DynVectorPrint(means,Ncols,'Variable Means',varlabels,count); - DynVectorPrint(variances,Ncols,'Variable Variances',varlabels,count); - DynVectorPrint(stddevs,Ncols,'Variable Standard Deviations',varlabels,count); - OutputFrm.ShowModal; - OutputFrm.RichEdit.Clear; - linecount := 0; - end; + lReport := TStringList.Create; + try + lReport.Add('HIERARCHICAL CLUSTER ANALYSIS'); + lReport.Add(''); + lReport.Add('Number of objects to cluster: %d on %d variables.', [Nrows, Ncols]); + lReport.Add(''); - // Standardize the distance scores if elected - if (StdChk.Checked) then - begin - for j := 0 to Ncols-1 do - for i := 0 to Nrows-1 do - Distance[i,j] := (Distance[i,j] - means[j]) / stddevs[j]; - end; + if StatsChk.Checked then + begin + DynVectorPrint(means, Ncols, 'Variable Means', varlabels, count, lReport); + DynVectorPrint(variances, Ncols, 'Variable Variances', varlabels, count, lReport); + DynVectorPrint(stddevs, Ncols, 'Variable Standard Deviations', varlabels, count, lReport); + lReport.Add(DIVIDER); + lReport.Add(''); + end; - if (ReplaceChk.Checked) then // replace original values in grid with z scores if elected - begin + // Standardize the distance scores if elected + if StdChk.Checked then + begin + for j := 0 to Ncols-1 do + for i := 0 to Nrows-1 do + Distance[i,j] := (Distance[i,j] - means[j]) / stddevs[j]; + end; + + // replace original values in grid with z scores if elected + if ReplaceChk.Checked then + begin for i := 1 to Nrows do begin - if (not GoodRecord(i,NoSelected,ColSelected)) then continue; + if not GoodRecord(i,NoSelected,ColSelected) then continue; for j := 1 to Ncols do begin col := ColSelected[j-1]; - outline := format('%6.4f',[Distance[i-1,j-1]]); - OS3MainFrm.DataGrid.Cells[col,i] := outline; + OS3MainFrm.DataGrid.Cells[col,i] := Format('%6.4f', [Distance[i-1,j-1]]); end; end; - end; + end; - // Convert data matrix to initial matrix of error potentials - for i := 1 to Nrows do - begin + // Convert data matrix to initial matrix of error potentials + for i := 1 to Nrows do + begin // if (not GoodRecord(i,NoSelected,ColSelected)) then continue; - for j := 1 to Ncols do W[j-1] := Distance[i-1,j-1]; - for j := i to Nrows do - begin + for j := 1 to Ncols do + W[j-1] := Distance[i-1,j-1]; + for j := i to Nrows do + begin // if (not GoodRecord(i,NoSelected,ColSelected)) then continue; - Distance[i-1,j-1] := 0.0; - for k := 1 to Ncols do Distance[i-1,j-1] := Distance[i-1,j-1] + - (Distance[j-1,k-1] - W[k-1]) * (Distance[j-1,k-1] - W[k-1]); - Distance[i-1,j-1] := Distance[i-1,j-1] / 2.0; - end; - end; - for i := 1 to Nrows do - for j := i to Nrows do Distance[j-1,i-1] := 0.0; - - // Now, group the cases for maximum groups down - if MaxGrpsChk.Checked then - begin - k1 := StrToInt(MaxGrps.Text); - n3 := Nrows; - end - else begin - k1 := 2; - n3 := Nrows; - end; - - // Initialize group membership and group-n vectors - for i := 0 to Nrows-1 do - begin - k4[i] := i+1; - k5[i] := i+1; - w2[i] := 1; - end; - - // Locate optimal combination, if more than 2 groups remain -next1: - n3 := n3 - 1; - if (n3 > 1) then - begin - x1 := 100000000000.0; - for i := 1 to Nrows do - begin - if (k5[i-1] = i) then - begin - for j := i to Nrows do - begin - if ((i <> j) and (k5[j-1] = j)) then - begin - d1 := Distance[i-1,j-1] - Distance[i-1,i-1] - Distance[j-1,j-1]; - if (d1 < x1) then - begin - x1 := d1; - L := i; - M := j; - end; // end if - end; // end if - end; // next j - end; // end if - end; // next i - n4 := w2[L-1]; - n5 := w2[M-1]; - - OutputFrm.RichEdit.Lines.Add(''); - linecount := linecount + 1; - GrpCnt := GrpCnt + 1; - XAxis[GrpCnt-1] := n3; - YAxis[GrpCnt-1] := x1; - if (x1 > MaxError) then MaxError := x1; - outline := format('%d groups after combining group %d (n := %d ) and group %d (n := %d) error := %7.3f', - [n3, L, n4, M, n5, x1]); - OutputFrm.RichEdit.Lines.Add(outline); - linecount := linecount + 1; - if (linecount >= 60) then - begin - OutputFrm.ShowModal; - OutputFrm.RichEdit.Clear; - linecount := 0; - end; - w3 := w2[L-1] + w2[M-1]; - x1 := Distance[L-1,M-1] * w3; - Y := Distance[L-1,L-1] * w2[L-1] + Distance[M-1,M-1] * w2[M-1]; - Distance[L-1,L-1] := Distance[L-1,M-1]; - for i := 1 to Nrows do - if (k5[i-1] = M) then k5[i-1] := L; - for i := 1 to Nrows do - begin - if ((i <> L) and (k5[i-1] = i)) then - begin - if (i <= L) then - begin - Distance[i-1,L-1] := Distance[i-1,L-1] * (w2[i-1] + w2[L-1]) - + Distance[i-1,M-1] * (w2[i-1] + w2[M-1]) - + x1 - Y - Distance[i-1,i-1] * w2[i-1]; - Distance[i-1,L-1] := Distance[i-1,L-1] / (w2[i-1] + w3); - end - else - begin - Distance[L-1,i-1] := Distance[L-1,i-1] * (w2[L-1] + w2[i-1]) - + (Distance[M-1,i-1] + Distance[i-1,M-1]) * (w2[M-1] + w2[i-1]); - Distance[L-1,i-1] := (Distance[L-1,i-1]+ x1 - Y - - Distance[i-1,i-1] * w2[i-1]) / (w2[i-1] + w3); - end; + Distance[i-1,j-1] := 0.0; + for k := 1 to Ncols do + Distance[i-1,j-1] := Distance[i-1,j-1] + (Distance[j-1,k-1] - W[k-1]) * (Distance[j-1,k-1] - W[k-1]); + Distance[i-1,j-1] := Distance[i-1,j-1] / 2.0; end; end; - w2[L-1] := w3; - if (n3 > k1) then goto next1; - - // print group memberships of all objects, if optioned for i := 1 to Nrows do + for j := i to Nrows do Distance[j-1,i-1] := 0.0; + + // Now, group the cases for maximum groups down + if MaxGrpsChk.Checked then begin - if (k5[i-1] = i) then + k1 := StrToInt(MaxGrps.Text); + n3 := Nrows; + end else + begin + k1 := 2; + n3 := Nrows; + end; + + // Initialize group membership and group-n vectors + for i := 0 to Nrows-1 do + begin + k4[i] := i+1; + k5[i] := i+1; + w2[i] := 1; + end; + + // Locate optimal combination, if more than 2 groups remain + +next1: + + n3 := n3 - 1; + if (n3 > 1) then + begin + x1 := 100000000000.0; + for i := 1 to Nrows do begin - L := 0; - for j := 1 to Nrows do + if (k5[i-1] = i) then begin - if (k5[j-1] = i) then + for j := i to Nrows do begin - L := L + 1; - L1[L-1] := k4[j-1]; - if k3 = 1 then L1[L-1] := j; + if ((i <> j) and (k5[j-1] = j)) then + begin + d1 := Distance[i-1,j-1] - Distance[i-1,i-1] - Distance[j-1,j-1]; + if (d1 < x1) then + begin + x1 := d1; + L := i; + M := j; + end; // end if + end; // end if + end; // next j + end; // end if + end; // next i + n4 := w2[L-1]; + n5 := w2[M-1]; + + GrpCnt := GrpCnt + 1; + XAxis[GrpCnt-1] := n3; + YAxis[GrpCnt-1] := x1; + if (x1 > MaxError) then MaxError := x1; + lReport.Add('%2.d groups after combining group %2.d (n = %2.d) and group %2.d (n = %2.d), error: %7.3f', [n3, L, n4, M, n5, x1]); + + w3 := w2[L-1] + w2[M-1]; + x1 := Distance[L-1,M-1] * w3; + Y := Distance[L-1,L-1] * w2[L-1] + Distance[M-1,M-1] * w2[M-1]; + Distance[L-1,L-1] := Distance[L-1,M-1]; + for i := 1 to Nrows do + if (k5[i-1] = M) then k5[i-1] := L; + for i := 1 to Nrows do + begin + if ((i <> L) and (k5[i-1] = i)) then + begin + if (i <= L) then + begin + Distance[i-1,L-1] := Distance[i-1,L-1] * (w2[i-1] + w2[L-1]) + + Distance[i-1,M-1] * (w2[i-1] + w2[M-1]) + + x1 - Y - Distance[i-1,i-1] * w2[i-1]; + Distance[i-1,L-1] := Distance[i-1,L-1] / (w2[i-1] + w3); + end else + begin + Distance[L-1,i-1] := Distance[L-1,i-1] * (w2[L-1] + w2[i-1]) + + (Distance[M-1,i-1] + Distance[i-1,M-1]) * (w2[M-1] + w2[i-1]); + Distance[L-1,i-1] := (Distance[L-1,i-1]+ x1 - Y + - Distance[i-1,i-1] * w2[i-1]) / (w2[i-1] + w3); end; end; - if k3 = 1 then - begin - outline := format('Group %d (n := %d)',[i,L]); - OutputFrm.RichEdit.Lines.Add(outline); - outline := ''; - for j := 1 to L do - begin - outline := format(' Object := %s',[rowlabels[L1[j-1]-1]]); - OutputFrm.RichEdit.Lines.Add(outline); - linecount := linecount + 1; - end; - if (linecount >= 60) then - begin - OutputFrm.ShowModal; - OutputFrm.RichEdit.Clear; - linecount := 0; - end; - end; // end if - end; // end if - end; // next i - goto next1; - end; // end if - if (linecount > 0) then OutputFrm.ShowModal; + end; + w2[L-1] := w3; + if (n3 > k1) then goto next1; - if (PlotChk.Checked) then - begin - SetLength(GraphFrm.Ypoints,1,GrpCnt); - SetLength(GraphFrm.Xpoints,1,GrpCnt); - for i := 1 to GrpCnt do - begin - GraphFrm.Ypoints[0,i-1] := YAxis[i-1]; - GraphFrm.Xpoints[0,i-1] := XAxis[i-1]; - end; - GraphFrm.nosets := 1; - GraphFrm.nbars := GrpCnt; - GraphFrm.Heading := 'NO. GROUPS VERSUS GROUPING ERROR'; - GraphFrm.XTitle := 'NO. GROUPS'; - GraphFrm.YTitle := 'ERROR'; + // print group memberships of all objects, if optioned + for i := 1 to Nrows do + begin + if (k5[i-1] = i) then + begin + L := 0; + for j := 1 to Nrows do + begin + if (k5[j-1] = i) then + begin + L := L + 1; + L1[L-1] := k4[j-1]; + if k3 = 1 then L1[L-1] := j; + end; + end; + if k3 = 1 then + begin + lReport.Add('Group %d (n = %d)', [i, L]); + for j := 1 to L do + lReport.Add(' Object: %s', [rowlabels[L1[j-1]-1]]); + end; // end if + end; // end if + end; // next i + goto next1; + end; // end if + + DisplayReport(lReport); + + if PlotChk.Checked then + begin + SetLength(GraphFrm.Ypoints,1,GrpCnt); + SetLength(GraphFrm.Xpoints,1,GrpCnt); + for i := 1 to GrpCnt do + begin + GraphFrm.Ypoints[0,i-1] := YAxis[i-1]; + GraphFrm.Xpoints[0,i-1] := XAxis[i-1]; + end; + GraphFrm.nosets := 1; + GraphFrm.nbars := GrpCnt; + GraphFrm.Heading := 'NO. GROUPS VERSUS GROUPING ERROR'; + GraphFrm.XTitle := 'NO. GROUPS'; + GraphFrm.YTitle := 'ERROR'; // GraphFrm.Ypoints[1] := YAxis; // GraphFrm.Xpoints[1] := XAxis; - GraphFrm.AutoScaled := true; - GraphFrm.PtLabels := false; - GraphFrm.GraphType := 7; // 2d points - GraphFrm.BackColor := clYellow; - GraphFrm.ShowBackWall := true; - GraphFrm.ShowModal; -end; + GraphFrm.AutoScaled := true; + GraphFrm.PtLabels := false; + GraphFrm.GraphType := 7; // 2d points + GraphFrm.BackColor := clCream; + GraphFrm.ShowBackWall := true; + GraphFrm.ShowModal; + end; - // clean up - ColSelected := nil; - rowlabels := nil; - varlabels := nil; - Distance := nil; - stddevs := nil; - variances := nil; - means := nil; - YAxis := nil; - XAxis := nil; - W := nil; - L1 := nil; - k5 := nil; - k4 := nil; - w2 := nil; - GraphFrm.Xpoints := nil; - GraphFrm.Ypoints := nil; + finally + lReport.Free; + ColSelected := nil; + rowlabels := nil; + varlabels := nil; + Distance := nil; + stddevs := nil; + variances := nil; + means := nil; + YAxis := nil; + XAxis := nil; + W := nil; + L1 := nil; + k5 := nil; + k4 := nil; + w2 := nil; + GraphFrm.Xpoints := nil; + GraphFrm.Ypoints := nil; + end; end; procedure THierarchFrm.PredInClick(Sender: TObject); -VAR i, index : integer; +var + i: integer; begin - index := VarList.Items.Count; - i := 0; - while i < index do - begin - if (VarList.Selected[i]) then - begin - PredList.Items.Add(VarList.Items.Strings[i]); - VarList.Items.Delete(i); - index := index - 1; - i := 0; - end - else i := i + 1; - end; - PredOut.Enabled := true; + i := 0; + while i < VarList.Items.Count do + begin + if VarList.Selected[i] then + begin + PredList.Items.Add(VarList.Items[i]); + VarList.Items.Delete(i); + i := 0; + end else + i := i + 1; + end; + UpdateBtnStates; end; procedure THierarchFrm.PredOutClick(Sender: TObject); -VAR index : integer; +var + i: integer; begin - index := PredList.ItemIndex; - if index < 0 then - begin - PredOut.Enabled := false; - exit; - end; - VarList.Items.Add(PredList.Items.Strings[index]); - PredList.Items.Delete(index); + i := 0; + while i < PredList.Items.Count do + begin + if PredList.Selected[i] then + begin + VarList.Items.Add(PredList.Items[i]); + PredList.Items.Delete(i); + i := 0; + end else + i := i + 1; + end; + UpdateBtnStates; +end; + +procedure THierarchFrm.UpdateBtnStates; +begin + PredIn.Enabled := AnySelected(VarList); + PredOut.Enabled := AnySelected(PredList); +end; + +procedure THierarchFrm.VarListSelectionChange(Sender: TObject; User: boolean); +begin + UpdateBtnStates; end; initialization diff --git a/applications/lazstats/source/forms/analysis/multivariate/pathunit.pas b/applications/lazstats/source/forms/analysis/multivariate/pathunit.pas index 6117b455a..4358328c6 100644 --- a/applications/lazstats/source/forms/analysis/multivariate/pathunit.pas +++ b/applications/lazstats/source/forms/analysis/multivariate/pathunit.pas @@ -325,12 +325,12 @@ end; procedure TPathFrm.ComputeBtnClick(Sender: TObject); var i, j, k, col, row, NoVars, nocaused, NoSelected, NoIndepVars : integer; - count, IER, noexogenous, t, L: integer; - constant, StdErrEst, ProbOut, R2, Temp, d2, sum, absdiff : double; + count, IER, noexogenous, L: integer; + constant, StdErrEst, ProbOut, R2, d2, sum, absdiff : double; cellstring: string; ColNoSelected, selected : IntDyneVec; IndepIndex : IntDyneVec; - rmat, WorkMat, PathCoef, IndMatrix, InvMatrix, e, W : DblDyneMat; + rmat, WorkMat, PathCoef, IndMatrix, e, W : DblDyneMat; means, variances, stddevs, beta, p : DblDyneVec; zvals : DblDyneMat; // z scores for path model genedz : IntDyneVec; // list of z's created for path models @@ -386,7 +386,6 @@ begin SetLength(WorkMat,NoVariables+1,NoVariables+1); SetLength(PathCoef,NoVariables,NoVariables); SetLength(IndMatrix,NoVariables,NoVariables); - SetLength(InvMatrix,NoVariables,NoVariables); SetLength(e,NoVariables,NoVariables); SetLength(W,NoVariables,NoVariables); SetLength(means,NoVariables); @@ -830,7 +829,6 @@ begin means := nil; W := nil; e := nil; - InvMatrix := nil; IndMatrix := nil; PathCoef := nil; WorkMat := nil; diff --git a/applications/lazstats/source/forms/analysis/nonparametric/kaplanmeierunit.pas b/applications/lazstats/source/forms/analysis/nonparametric/kaplanmeierunit.pas index 1a8899ec4..972525e57 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/kaplanmeierunit.pas +++ b/applications/lazstats/source/forms/analysis/nonparametric/kaplanmeierunit.pas @@ -208,7 +208,7 @@ var Size1, Size2, TotalSize, NoDeaths, ThisTime: integer; mintime, maxtime, tempint, nopoints, tempvalue : integer; NoCensored, nocats, i, j, k, icase, oldtime, pos, first, last : integer; - noinexp, noincntrl, count, TimeCol, DeathsCol, CensoredCol : integer; + noinexp, noincntrl, count, TimeCol, DeathsCol: integer; GroupCol : integer; cumprop, proportion, term1, term2, term3 : double; E1, E2, O1, O2, Chisquare, ProbChi, Risk, LogRisk, SELogRisk : double; @@ -227,7 +227,6 @@ begin DeathsLabel := EventEdit.Text; TimeCol := 0; DeathsCol := 0; - CensoredCol := 0; GroupCol := 0; for i := 1 to NoVariables do begin diff --git a/applications/lazstats/source/units/dataprocs.pas b/applications/lazstats/source/units/dataprocs.pas index 5c1cc6d0f..7ce009bd0 100644 --- a/applications/lazstats/source/units/dataprocs.pas +++ b/applications/lazstats/source/units/dataprocs.pas @@ -65,7 +65,6 @@ uses MainUnit; Function GoodRecord(Row, NoVars: integer; const GridPos: IntDyneVec): boolean; var i, j: integer; - isgood: boolean; begin Result := true; for i := 1 to NoVars do