RIDITUnit: Usual refactoring. Some improvements in report layout. Less hints/warnings.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7358 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-04-05 17:25:38 +00:00
parent eac8c9b0a4
commit 8b0581017d
6 changed files with 588 additions and 592 deletions

View File

@ -166,7 +166,7 @@ var
MatInput : boolean;
Title : string;
filename : string;
Save_Cursor : TCursor;
// Save_Cursor : TCursor;
errorcode : boolean = false;
begin
MaxRoot := 0.0;
@ -525,7 +525,7 @@ again:
FACTORS(Eigenvector, d2, ainverse, k, factorchoice);
factREORDER(Eigenvector, ainverse, RowLabels, k);
end;
Screen.Cursor := Save_Cursor; // restore regular cursor
// Screen.Cursor := Save_Cursor; // restore regular cursor
for i := 1 to k do
for j := 1 to k do

View File

@ -1,11 +1,11 @@
object RIDITFrm: TRIDITFrm
Left = 520
Height = 369
Top = 238
Left = 1022
Height = 364
Top = 285
Width = 665
AutoSize = True
Caption = 'Relative to an Identified Distribution Analysis'
ClientHeight = 369
ClientHeight = 364
ClientWidth = 665
OnActivate = FormActivate
OnCreate = FormCreate
@ -104,12 +104,12 @@ object RIDITFrm: TRIDITFrm
AnchorSideRight.Side = asrBottom
Left = 400
Height = 72
Top = 180
Top = 176
Width = 257
Anchors = [akTop, akRight]
AutoFill = True
AutoSize = True
BorderSpacing.Top = 16
BorderSpacing.Top = 12
BorderSpacing.Right = 8
Caption = 'Reference Variable'
ChildSizing.LeftRightSpacing = 12
@ -141,7 +141,7 @@ object RIDITFrm: TRIDITFrm
Top = 260
Width = 167
BorderSpacing.Left = 12
BorderSpacing.Top = 8
BorderSpacing.Top = 12
BorderSpacing.Right = 8
Caption = 'Use Bonferroni for contrasts'
TabOrder = 3
@ -164,92 +164,74 @@ object RIDITFrm: TRIDITFrm
Text = 'AlphaEdit'
end
object ResetBtn: TButton
AnchorSideRight.Control = CancelBtn
AnchorSideRight.Control = ComputeBtn
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 364
Left = 452
Height = 25
Top = 336
Top = 331
Width = 54
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 8
BorderSpacing.Top = 8
BorderSpacing.Right = 12
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
Caption = 'Reset'
OnClick = ResetBtnClick
TabOrder = 6
end
object CancelBtn: TButton
AnchorSideRight.Control = ComputeBtn
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 430
Height = 25
Top = 336
Width = 62
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 8
BorderSpacing.Top = 8
BorderSpacing.Right = 12
BorderSpacing.Bottom = 8
Caption = 'Cancel'
ModalResult = 2
TabOrder = 7
end
object ReturnBtn: TButton
object CloseBtn: TButton
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 592
Left = 598
Height = 25
Top = 336
Width = 61
Top = 331
Width = 55
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 8
BorderSpacing.Top = 8
BorderSpacing.Right = 12
BorderSpacing.Bottom = 8
Caption = 'Return'
ModalResult = 1
TabOrder = 8
Caption = 'Close'
ModalResult = 11
TabOrder = 7
end
object ComputeBtn: TButton
AnchorSideRight.Control = ReturnBtn
AnchorSideRight.Control = CloseBtn
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 504
Left = 514
Height = 25
Top = 336
Top = 331
Width = 76
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 8
BorderSpacing.Top = 8
BorderSpacing.Right = 12
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
Caption = 'Compute'
OnClick = ComputeBtnClick
TabOrder = 9
TabOrder = 8
end
object HelpBtn: TButton
Tag = 143
AnchorSideRight.Control = ResetBtn
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 301
Left = 393
Height = 25
Top = 336
Top = 331
Width = 51
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 8
BorderSpacing.Top = 8
BorderSpacing.Right = 12
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
Caption = 'Help'
OnClick = HelpBtnClick
@ -259,10 +241,10 @@ object RIDITFrm: TRIDITFrm
AnchorSideLeft.Control = Owner
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = ReturnBtn
AnchorSideBottom.Control = CloseBtn
Left = 0
Height = 8
Top = 320
Height = 6
Top = 317
Width = 665
Anchors = [akLeft, akRight, akBottom]
Shape = bsBottomLine
@ -273,13 +255,13 @@ object RIDITFrm: TRIDITFrm
AnchorSideRight.Control = RefGrp
AnchorSideBottom.Control = Bevel1
Left = 0
Height = 312
Height = 309
Top = 0
Width = 400
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Bottom = 8
BevelOuter = bvNone
ClientHeight = 312
ClientHeight = 309
ClientWidth = 400
TabOrder = 0
object Label1: TLabel
@ -321,7 +303,7 @@ object RIDITFrm: TRIDITFrm
AnchorSideBottom.Control = RefEdit
Left = 222
Height = 15
Top = 272
Top = 269
Width = 96
Anchors = [akLeft, akBottom]
BorderSpacing.Top = 8
@ -337,7 +319,7 @@ object RIDITFrm: TRIDITFrm
AnchorSideBottom.Control = Panel1
AnchorSideBottom.Side = asrBottom
Left = 8
Height = 287
Height = 284
Top = 25
Width = 170
Anchors = [akTop, akLeft, akRight, akBottom]
@ -346,6 +328,7 @@ object RIDITFrm: TRIDITFrm
BorderSpacing.Right = 8
ItemHeight = 0
MultiSelect = True
OnSelectionChange = VarListSelectionChange
TabOrder = 0
end
object RowIn: TBitBtn
@ -424,6 +407,7 @@ object RIDITFrm: TRIDITFrm
Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 8
BorderSpacing.Bottom = 12
ReadOnly = True
TabOrder = 3
Text = 'RowEdit'
end
@ -436,7 +420,7 @@ object RIDITFrm: TRIDITFrm
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = Label4
Left = 222
Height = 130
Height = 127
Top = 134
Width = 170
Anchors = [akTop, akLeft, akRight, akBottom]
@ -445,6 +429,7 @@ object RIDITFrm: TRIDITFrm
BorderSpacing.Right = 8
ItemHeight = 0
OnClick = ColListClick
OnSelectionChange = VarListSelectionChange
TabOrder = 6
end
object RefEdit: TEdit
@ -456,11 +441,12 @@ object RIDITFrm: TRIDITFrm
AnchorSideBottom.Side = asrBottom
Left = 222
Height = 23
Top = 289
Top = 286
Width = 170
Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 8
BorderSpacing.Right = 8
ReadOnly = True
TabOrder = 7
Text = 'RefEdit'
end

View File

@ -21,8 +21,7 @@ type
HelpBtn: TButton;
Panel1: TPanel;
ResetBtn: TButton;
CancelBtn: TButton;
ReturnBtn: TButton;
CloseBtn: TButton;
ComputeBtn: TButton;
Label5: TLabel;
ObsChk: TCheckBox;
@ -60,11 +59,12 @@ type
procedure Analyze(RefCol: integer; ColNoSelected: IntDyneVec;
RowLabels: StrDyneVec; ColLabels: StrDyneVec;
NoToAnalyze: integer; Freq: IntDyneMat;
Props : DblDyneMat; NoRows : integer);
Props: DblDyneMat; NoRows: integer; AReport: TStrings);
procedure VarListSelectionChange(Sender: TObject; User: boolean);
private
{ private declarations }
FAutoSized: Boolean;
procedure UpdateBtnStates;
public
{ public declarations }
end;
@ -75,46 +75,50 @@ var
implementation
uses
Math;
Math,
Utils;
{ TRIDITFrm }
procedure TRIDITFrm.ResetBtnClick(Sender: TObject);
VAR i : integer;
var
i: integer;
begin
VarList.Clear;
ColList.Clear;
RowEdit.Text := '';
RefEdit.Text := '';
AlphaEdit.Text := '0.05';
AlphaEdit.Text := FormatFloat('0.00', DEFAULT_ALPHA_LEVEL);
BonChk.Checked := true;
RowIn.Enabled := true;
RowOut.Enabled := false;
ColIn.Enabled := true;
ColOut.Enabled := false;
Label4.Visible := false;
RefEdit.Visible := false;
RefGrp.ItemIndex := 1;
RefGrp.ItemIndex := 0;
for i := 1 to NoVariables do
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
UpdateBtnStates;
end;
procedure TRIDITFrm.RowInClick(Sender: TObject);
VAR index : integer;
var
index: integer;
begin
index := VarList.ItemIndex;
RowEdit.Text := VarList.Items.Strings[index];
if (index > -1) and (RowEdit.Text = '') then
begin
RowEdit.Text := VarList.Items[index];
VarList.Items.Delete(index);
RowIn.Enabled := false;
RowOut.Enabled := true;
end;
UpdateBtnStates;
end;
procedure TRIDITFrm.RowOutClick(Sender: TObject);
begin
if RowEdit.Text <> '' then
begin
VarList.Items.Add(RowEdit.Text);
RowEdit.Text := '';
RowIn.Enabled := true;
RowOut.Enabled := false;
end;
UpdateBtnStates;
end;
procedure TRIDITFrm.FormActivate(Sender: TObject);
@ -123,12 +127,11 @@ var
begin
if FAutoSized then
exit;
w := MaxValue([HelpBtn.Width, ResetBtn.Width, CancelBtn.Width, ComputeBtn.Width, ReturnBtn.Width]);
w := MaxValue([HelpBtn.Width, ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]);
HelpBtn.Constraints.MinWidth := w;
ResetBtn.Constraints.MinWidth := w;
CancelBtn.Constraints.MinWidth := w;
ComputeBtn.Constraints.MinWidth := w;
ReturnBtn.Constraints.MinWidth := w;
CloseBtn.Constraints.MinWidth := w;
Constraints.MinWidth := Width;
Constraints.MinHeight := Height;
@ -139,8 +142,6 @@ end;
procedure TRIDITFrm.FormCreate(Sender: TObject);
begin
Assert(OS3MainFrm <> nil);
if OutputFrm = nil then
Application.CreateForm(TOutputFrm, OutputFrm);
end;
procedure TRIDITFrm.FormShow(Sender: TObject);
@ -157,61 +158,53 @@ end;
procedure TRIDITFrm.RefGrpClick(Sender: TObject);
begin
if (RefGrp.ItemIndex = 0) then // do all variables as reference variable
begin
Label4.Visible := false;
RefEdit.Visible := false;
end
else
begin
Label4.Visible := true;
RefEdit.Visible := true;
end;
RefEdit.Visible := RefGrp.ItemIndex > 0;
Label4.Visible := RefEdit.Visible;
end;
procedure TRIDITFrm.ColInClick(Sender: TObject);
VAR index, i : integer;
var
i: integer;
begin
index := VarList.Items.Count;
i := 0;
while (i < index) do
while (i < VarList.Items.Count) do
begin
if (VarList.Selected[i]) then
if VarList.Selected[i] then
begin
ColList.Items.Add(VarList.Items.Strings[i]);
ColList.Items.Add(VarList.Items[i]);
VarList.Items.Delete(i);
index := index - 1;
i := 0;
end
else i := i + 1;
end else
i := i + 1;
end;
ColOut.Enabled := true;
UpdateBtnStates;
end;
procedure TRIDITFrm.ColListClick(Sender: TObject);
VAR index : integer;
var
index: integer;
begin
index := ColList.ItemIndex;
RefEdit.Text := ColList.Items.Strings[index];
if index > -1 then
RefEdit.Text := ColList.Items[index];
UpdateBtnStates;
end;
procedure TRIDITFrm.ColOutClick(Sender: TObject);
VAR index : integer;
var
index: integer;
begin
index := ColList.ItemIndex;
if (index < 0) then
if index > -1 then
begin
ColOut.Enabled := false;
exit;
end;
VarList.Items.Add(ColList.Items.Strings[index]);
VarList.Items.Add(ColList.Items[index]);
ColList.Items.Delete(index);
end;
UpdateBtnStates;
end;
procedure TRIDITFrm.ComputeBtnClick(Sender: TObject);
VAR
var
AllRefs : boolean;
i, j, RowNo, RefColNo, NoToAnalyze : integer;
Row, Col, Ncases, Nrows, Ncols, df : integer;
@ -224,14 +217,34 @@ VAR
ChiSquare, ProbChi : double;
yates : boolean;
Adjchisqr, Adjprobchi: double;
liklihood, probliklihood, phi : double;
likelihood, problikelihood, phi: double;
pearsonr, VarX, VarY, SumX, SumY, MantelHaenszel, MHProb, CoefCont: double;
CramerV: double;
tmp: Double;
lReport: TStrings;
begin
AllRefs := true;
if (RefGrp.ItemIndex = 1) then AllRefs := false;
if AlphaEdit.Text = '' then
begin
AlphaEdit.SetFocus;
MessageDlg('Alpha level not specified.', mtError, [mbOK], 0);
exit;
end;
if not TryStrToFloat(AlphaEdit.Text, tmp) then
begin
AlphaEdit.Setfocus;
MessageDlg('Numeric input required for alpha level.', mtError, [mbOK], 0);
exit;
end;
if (tmp <= 0) or (tmp >= 1) then
begin
AlphaEdit.Setfocus;
MessageDlg('Alpha level must be > 0 and < 1', mtError, [mbOK], 0);
exit;
end;
AllRefs := RefGrp.ItemIndex = 0;
SetLength(ColNoSelected,NoVariables+1);
yates := false;
RowNo := 0;
for i := 1 to NoVariables do
begin
@ -246,6 +259,7 @@ begin
return;
end;
}
Nrows := NoCases;
Ncols := ColList.Items.Count;
SetLength(RowLabels,Nrows+1);
@ -253,7 +267,7 @@ begin
if (RowNo = 0) then
begin
ShowMessage('ERROR! A variable for the row labels was not entered.');
MessageDlg('A variable for the row labels was not entered.', mtError, [mbOK], 0);
ColNoSelected := nil;
exit;
end;
@ -283,9 +297,7 @@ begin
// Get row labels
for i := 1 to NoCases do
begin
RowLabels[i-1] := OS3MainFrm.DataGrid.Cells[RowNo,i];
end;
// allocate and initialize
SetLength(Freq, Nrows+1, Ncols+1);
@ -293,7 +305,8 @@ begin
SetLength(Expected, Nrows, Ncols);
SetLength(CellChi, Nrows, Ncols);
for i := 1 to Nrows + 1 do
for j := 1 to Ncols + 1 do Freq[i-1,j-1] := 0;
for j := 1 to Ncols + 1 do
Freq[i-1,j-1] := 0;
RowLabels[Nrows] := 'Total';
ColLabels[Ncols] := 'Total';
@ -315,28 +328,22 @@ begin
Freq[Nrows][Ncols] := Ncases;
// Now, calculate expected values
// Get row totals first
for i := 1 to Nrows do
begin
for j := 1 to Ncols do
begin
Freq[i-1,Ncols] := Freq[i-1,Ncols] + Freq[i-1,j-1];
end;
end;
// Get col totals next
for j := 1 to Ncols do
begin
for i := 1 to Nrows do
begin
Freq[Nrows,j-1] := Freq[Nrows,j-1] + Freq[i-1,j-1];
end;
end;
// Then get expected values and cell chi-squares
ChiSquare := 0.0;
Adjchisqr := 0.0;
if ((YatesChk.Checked) and (Nrows = 2) and (Ncols = 2)) then yates := true;
if ((Nrows > 1) and (Ncols > 1)) then
yates := YatesChk.Checked and (Nrows = 2) and (Ncols = 2);
if (Nrows > 1) and (Ncols > 1) then
begin
for i := 1 to Nrows do
begin
@ -344,18 +351,18 @@ begin
begin
Expected[i-1,j-1] := Freq[Nrows,j-1] * Freq[i-1,Ncols] / Ncases;
if (Expected[i-1,j-1] > 0.0) then
CellChi[i-1,j-1] := sqr(Freq[i-1,j-1] - Expected[i-1,j-1])
/ Expected[i-1,j-1]
CellChi[i-1,j-1] := sqr(Freq[i-1,j-1] - Expected[i-1,j-1])/ Expected[i-1,j-1]
else
begin
ShowMessage('ERROR! Zero expected value found.');
MessageDlg('Zero expected value found.', mtError, [mbOK], 0);
CellChi[i-1,j-1] := 0.0;
end;
ChiSquare := ChiSquare + CellChi[i-1,j-1];
end;
end;
df := (Nrows - 1) * (Ncols - 1);
if (yates = true) then // 2 x 2 corrected chi-square
if yates then // 2 x 2 corrected chi-square
begin
Adjchisqr := abs((Freq[0,0] * Freq[1,1]) - (Freq[0,1] * Freq[1,0]));
Adjchisqr := sqr(Adjchisqr - Ncases / 2.0) * Ncases; // numerator
@ -363,6 +370,7 @@ begin
Adjprobchi := 1.0 - chisquaredprob(Adjchisqr,df);
end;
end;
if (Nrows = 1) then // equal probability
begin
for j := 0 to Ncols - 1 do
@ -390,94 +398,97 @@ begin
ProbChi := 1.0 - chisquaredprob(ChiSquare,df); // prob. larger chi
//Print results to output form
OutputFrm.RichEdit.Clear;
OutputFrm.RichEdit.Lines.Add('Chi-square Analysis Results');
outline := format('No. of Cases = %d',[Ncases]);
OutputFrm.RichEdit.Lines.Add(outline);
OutputFrm.RichEdit.Lines.Add('');
lReport := TStringList.Create;
try
lReport.Add('CHI-SQUARE ANALYSIS RESULTS');
lReport.Add('No. of Cases: %d', [Ncases]);
lReport.Add('');
// print tables requested by use
if (ObsChk.Checked) then
begin
IntArrayPrint(Freq, Nrows+1, Ncols+1,'Frequencies',
RowLabels, ColLabels,'OBSERVED FREQUENCIES');
end;
if ObsChk.Checked then
IntArrayPrint(Freq, Nrows+1, Ncols+1, 'Frequencies', RowLabels, ColLabels, 'OBSERVED FREQUENCIES', lReport);
if (ExpChk.Checked) then
if ExpChk.Checked then
begin
outline := 'EXPECTED FREQUENCIES';
MAT_PRINT(Expected, Nrows, Ncols, outline, RowLabels, ColLabels,
NoCases);
MatPrint(Expected, Nrows, Ncols, outline, RowLabels, ColLabels, NoCases, lReport);
end;
if (PropChk.Checked) then outline := 'ROW PROPORTIONS';
for i := 1 to Nrows + 1 do
begin
for j := 1 to Ncols do
begin
if (Freq[i-1,Ncols] > 0.0) then
Prop[i-1,j-1] := Freq[i-1,j-1] / Freq[i-1,Ncols]
else Prop[i-1,j-1] := 0.0;
else
Prop[i-1,j-1] := 0.0;
end;
if (Freq[i-1,Ncols] > 0.0) then Prop[i-1,Ncols] := 1.0
else Prop[i-1,Ncols] := 0.0;
if (Freq[i-1,Ncols] > 0.0) then
Prop[i-1,Ncols] := 1.0
else
Prop[i-1,Ncols] := 0.0;
end;
if (PropChk.Checked) then
MAT_PRINT(Prop, Nrows+1, Ncols+1, outline, RowLabels, ColLabels,
NoCases);
if (PropChk.Checked) then outline := 'COLUMN PROPORTIONS';
if PropChk.Checked then
begin
outline := 'ROW PROPORTIONS';
MatPrint(Prop, Nrows+1, Ncols+1, outline, RowLabels, ColLabels, NoCases, lReport);
end;
for j := 1 to Ncols + 1 do
begin
for i := 1 to Nrows do
begin
if (Freq[Nrows,j-1] > 0.0) then
Prop[i-1,j-1] := Freq[i-1,j-1] / Freq[Nrows,j-1]
else Prop[i-1,j-1] := 0.0;
else
Prop[i-1,j-1] := 0.0;
end;
if (Freq[Nrows,j-1] > 0.0) then Prop[Nrows,j-1] := 1.0
else Prop[Nrows,j-1] := 0.0;
if (Freq[Nrows,j-1] > 0.0) then
Prop[Nrows,j-1] := 1.0
else
Prop[Nrows,j-1] := 0.0;
end;
if (PropChk.Checked) then
MAT_PRINT(Prop, Nrows+1, Ncols+1, outline, RowLabels, ColLabels,
NoCases);
begin
outline := 'COLUMN PROPORTIONS';
MatPrint(Prop, Nrows+1, Ncols+1, outline, RowLabels, ColLabels, NoCases, lReport);
end;
if (ChiChk.Checked) then
if ChiChk.Checked then
begin
outline := 'CHI-SQUARED VALUE FOR CELLS';
MAT_PRINT(CellChi, Nrows, Ncols, outline, RowLabels, ColLabels,
NoCases);
MatPrint(CellChi, Nrows, Ncols, outline, RowLabels, ColLabels, NoCases, lReport);
end;
OutputFrm.RichEdit.Lines.Add('');
outline := format('Chi-square = %8.3f with D.F. = %d. Prob. > value = %8.3f',
[ChiSquare,df,ProbChi]);
OutputFrm.RichEdit.Lines.Add(outline);
OutputFrm.RichEdit.Lines.Add('');
if (yates = true) then
lReport.Add('');
lReport.Add( 'Chi-square: %8.3f', [ChiSquare]);
lReport.Add( ' with D.F. %8d', [df]);
lReport.Add( ' and Probability > value: %8.3f', [ProbChi]);
lReport.Add('');
if yates then
begin
outline := format('Chi-square using Yates correction = %8.3f and Prob > value = %8.3f',
[Adjchisqr,Adjprobchi]);
OutPutFrm.RichEdit.Lines.Add(outline);
lReport.Add('Chi-square using Yates correction: %8.3f', [AdjChiSqr]);
lReport.Add(' and Probability > value: %8.3f', [Adjprobchi]);
end;
liklihood := 0.0;
likelihood := 0.0;
for i := 0 to Nrows - 1 do
for j := 0 to Ncols - 1 do
if (Freq[i,j] > 0.0) then
liklihood := liklihood + Freq[i,j] * (ln(Expected[i,j] / Freq[i,j]));
liklihood := -2.0 * liklihood;
probliklihood := 1.0 - chisquaredprob(liklihood,df);
outline := format('Liklihood Ratio = %8.3f with prob. > value = %6.4f',
[liklihood,probliklihood]);
OutputFrm.RichEdit.Lines.Add(outline);
OutputFrm.RichEdit.Lines.Add('');
likelihood := likelihood + Freq[i,j] * (ln(Expected[i,j] / Freq[i,j]));
likelihood := -2.0 * likelihood;
problikelihood := 1.0 - ChiSquaredProb(likelihood, df);
lReport.Add( 'Likelihood Ratio: %8.3f', [likelihood]);
lReport.Add( ' with Probability > value: %8.4f', [problikelihood]);
lReport.Add('');
if ((Nrows > 1) and (Ncols > 1)) then
begin
phi := sqrt(ChiSquare / Ncases);
outline := format('phi correlation = %6.4f',[phi]);
OutputFrm.RichEdit.Lines.Add(outline);
OutputFrm.RichEdit.Lines.Add('');
lReport.Add('phi correlation: %8.4f', [phi]);
lReport.Add('');
pearsonr := 0.0;
SumX := 0.0;
@ -495,59 +506,59 @@ begin
pearsonr := pearsonr + ((i+1)*(j+1) * Freq[i,j]);
pearsonr := pearsonr - (SumX * SumY / Ncases);
pearsonr := pearsonr / sqrt(VarX * VarY);
outline := format('Pearson Correlation r = %6.4f',[pearsonr]);
OutputFrm.RichEdit.Lines.Add(outline);
OutputFrm.RichEdit.Lines.Add('');
lReport.Add('Pearson Correlation r: %8.4f', [pearsonr]);
lReport.Add('');
MantelHaenszel := (Ncases-1) * (pearsonr * pearsonr);
MHprob := 1.0 - chisquaredprob(MantelHaenszel,1);
outline := format('Mantel-Haenszel Test of Linear Association = %8.3f with probability > value = %6.4f',
[MantelHaenszel, MHprob]);
OutputFrm.RichEdit.Lines.Add(outline);
OutputFrm.RichEdit.Lines.Add('');
lReport.Add('Mantel-Haenszel Test of Linear Association: %.3f with probability > value %.4f', [MantelHaenszel, MHprob]);
lReport.Add('');
CoefCont := sqrt(ChiSquare / (ChiSquare + Ncases));
outline := format('The coefficient of contingency = %8.3f',[CoefCont]);
OutputFrm.RichEdit.Lines.Add(outline);
OutputFrm.RichEdit.Lines.Add('');
lReport.Add('The coefficient of contingency: %8.3f', [CoefCont]);
lReport.Add('');
if (Nrows < Ncols) then CramerV := sqrt(ChiSquare / (Ncases * ((Nrows-1))))
else CramerV := sqrt(ChiSquare / (Ncases * ((Ncols-1))));
outline := format('Cramers V = %8.3f',[CramerV]);
OutputFrm.RichEdit.Lines.Add(outline);
if (Nrows < Ncols) then
CramerV := sqrt(ChiSquare / (Ncases * ((Nrows-1))))
else
CramerV := sqrt(ChiSquare / (Ncases * ((Ncols-1))));
lReport.Add('Cramers V: %8.3f', [CramerV]);
end;
OutputFrm.ShowModal();
OutputFrm.RichEdit.Clear();
lReport.Add('');
lReport.Add('=============================================================================');
lReport.Add('');
// Now do RIDIT analysis
NoToAnalyze := ColList.Items.Count;
if (AllRefs) then // do an analysis for each variable as a reference variable
// do an analysis for each variable as a reference variable
if AllRefs then
begin
NoToAnalyze := ColList.Items.Count;
for i := 0 to NoToAnalyze - 1 do
begin
RefColNo := ColNoSelected[i+1] - 2;
Analyze(RefColNo, ColNoSelected, RowLabels,ColLabels,
NoToAnalyze,Freq,Prop, Nrows);
Analyze(RefColNo, ColNoSelected, RowLabels,ColLabels, NoToAnalyze, Freq, Prop, Nrows, lReport);
end;
end
else // only one selected reference variable
end else
// only one selected reference variable
begin
NoToAnalyze := ColList.Items.Count;
// get column of reference variable
for i := 1 to NoVariables do
begin
if (RefEdit.Text = OS3MainFrm.DataGrid.Cells[i,0]) then RefColNo := i;
end;
for j := 0 to NoToAnalyze - 1 do
begin
if (ColNoSelected[j+1] = RefColNo) then RefColNo := j;
Analyze(RefColNo, ColNoSelected, RowLabels,ColLabels, NoToAnalyze, Freq, Prop, Nrows, lReport);
end;
Analyze(RefColNo, ColNoSelected, RowLabels,ColLabels,
NoToAnalyze,Freq, Prop, Nrows);
end;
DisplayReport(lReport);
finally
lReport.Free;
ColLabels := nil;
RowLabels := nil;
@ -557,12 +568,14 @@ begin
Freq := nil;
ColNoSelected := nil;
end;
end;
procedure TRIDITFrm.Analyze(RefCol : integer; ColNoSelected : IntDyneVec;
RowLabels : StrDyneVec; ColLabels : StrDyneVec;
NoToAnalyze : integer; Freq : IntDyneMat;
Props : DblDyneMat; NoRows : integer);
VAR
Props : DblDyneMat; NoRows : integer;
AReport: TStrings);
var
probdists : DblDyneMat;
refprob : DblDyneMat;
sizes : DblDyneVec;
@ -576,12 +589,10 @@ VAR
Bonferroni : double;
i, j : integer;
outline : string;
outstring : string;
details : boolean;
term1,term2,term3,term4 : double;
begin
details := false;
SetLength(probdists,NoRows,NoToAnalyze);
SetLength(refprob,NoRows,4);
SetLength(sizes,NoToAnalyze);
@ -590,27 +601,23 @@ begin
SetLength(StdErr,NoToAnalyze);
alpha := StrToFloat(AlphaEdit.Text);
if (DetailsChk.Checked) then details := true;
details := DetailsChk.Checked;
outline := format('ANALYSIS FOR STANDARD %s',[ColLabels[RefCol]]);
OutputFrm.RichEdit.Lines.Add(outline);
OutputFrm.RichEdit.Lines.Add('');
AReport.Add('ANALYSIS FOR STANDARD %s', [ColLabels[RefCol]]);
// AReport.Add('');
// print frequencies
outline := 'Frequencies Observed';
IntArrayPrint(Freq, NoRows, NoToAnalyze, 'Frequencies', RowLabels, ColLabels,
outline);
IntArrayPrint(Freq, NoRows, NoToAnalyze, 'Frequencies', RowLabels, ColLabels, outline, AReport);
// print column proportions
outline := 'Column Proportions Observed';
MAT_PRINT(Props, NoRows, NoToAnalyze, outline, RowLabels, ColLabels,
NoCases);
MatPrint(Props, NoRows, NoToAnalyze, outline, RowLabels, ColLabels, NoCases, AReport);
// Get sizes in each column
for i := 0 to NoToAnalyze - 1 do
begin
sizes[i] := Freq[NoRows,i];
end;
// Get the reference variable probabilities for all variables
for j := 0 to NoToAnalyze - 1 do
begin
@ -624,98 +631,81 @@ begin
for i := 0 to NoRows - 1 do refprob[i,3] := refprob[i,1] + refprob[i,2];
if (details) then // print calculations table
begin
outstring := 'Ridit calculations for ' + ColLabels[j];
outline := outstring;
MAT_PRINT(refprob, NoRows, 4, outline, RowLabels, ColLabels,
NoCases);
outline := 'Ridit calculations for ' + ColLabels[j];
MatPrint(refprob, NoRows, 4, outline, RowLabels, ColLabels, NoCases, AReport);
end;
// store results in probdists
for i := 0 to NoRows - 1 do probdists[i,j] := refprob[i,3];
end;
outstring := 'Ridits for all variables';
outline := outstring;
MAT_PRINT(probdists, NoRows, NoToAnalyze, outline, RowLabels, ColLabels,
NoCases);
outline := 'Ridits for all variables';
MatPrint(probdists, NoRows, NoToAnalyze, outline, RowLabels, ColLabels, NoCases, AReport);
// obtain mean ridits for the all variables using the reference variable
for i := 0 to NoToAnalyze - 1 do
begin
meanridits[i] := 0.0;
for j := 0 to NoRows - 1 do
begin
meanridits[i] := meanridits[i] + (probdists[j,RefCol] * Freq[j,i]);
end;
meanridits[i] := meanridits[i] / sizes[i];
end;
// print the means using the reference variable
outline := 'Mean RIDITS Using the Reference Values';
DynVectorPrint(meanridits,NoToAnalyze,outline,ColLabels,NoCases);
DynVectorPrint(meanridits, NoToAnalyze, outline, ColLabels, NoCases, AReport);
// obtain the weighted grand mean ridit
OverMeanRidit := 0.0;
for i := 0 to NoToAnalyze - 1 do
begin
if (i <> RefCol) then OverMeanRidit := OverMeanRidit + sizes[i] * meanridits[i];
end;
OverMeanRidit := OverMeanRidit / (Freq[NoRows,NoToAnalyze] - sizes[RefCol]);
outline := format('Overall mean for RIDITS in non-reference groups := %8.4f',[OverMeanRidit]);
OutputFrm.RichEdit.Lines.Add(outline);
AReport.Add('Overall mean for RIDITS in non-reference groups: %8.4f', [OverMeanRidit]);
// obtain chisquare
chisquare := 0.0;
term4 := (OverMeanRidit - 0.5) * (OverMeanRidit - 0.5);
term4 := sqr(OverMeanRidit - 0.5);
term3 := 0.0;
for i := 0 to NoToAnalyze - 1 do
begin
if (i <> RefCol) then term3 := term3 + (sizes[i] * sizes[i]);
end;
if (i <> RefCol) then term3 := term3 + sizes[i] * sizes[i];
term3 := 12.0 * term3;
term2 := Freq[NoRows,NoToAnalyze];
term1 := 0.0;
for i := 0 to NoToAnalyze - 1 do
begin
if (i <> RefCol) then
term1 := term1 + (sizes[i] * ((meanridits[i] - 0.5) * (meanridits[i] - 0.5)));
end;
term1 := term1 + sizes[i] * sqr(meanridits[i] - 0.5);
term1 := term1 * 12.0;
chisquare := term1 - ((term3 / term2) * term4);
probchi := 1.0 - chisquaredprob(chisquare,NoToAnalyze-1);
outline := format('Chisquared := %8.3f with probability < %8.4f',[chisquare,probchi]);
OutputFrm.RichEdit.Lines.Add(outline);
chisquare := term1 - (term3 / term2) * term4;
probchi := 1.0 - ChiSquaredProb(chisquare, NoToAnalyze-1);
AReport.Add('Chisquared: %8.4f', [chisquare]);
AReport.Add(' with probability < %8.4f', [probchi]);
// do pairwise comparisons
Cratios[RefCol] := 0.0;
for i := 0 to NoToAnalyze - 1 do
begin
if (i <> RefCol) then
begin
StdErr[i] := sqrt(sizes[RefCol] + sizes[i]) /
(2.0 * sqrt(3.0 * sizes[RefCol] * sizes[i]));
StdErr[i] := sqrt(sizes[RefCol] + sizes[i]) / (2.0 * sqrt(3.0 * sizes[RefCol] * sizes[i]));
Cratios[i] := (meanridits[i] - 0.5) / StdErr[i];
end;
end;
outline := 'z critical ratios';
DynVectorPrint(Cratios,NoToAnalyze,outline,ColLabels,NoCases);
DynVectorPrint(Cratios, NoToAnalyze, outline, ColLabels, NoCases, AReport);
alpha := alpha / 2.0;
if (BonChk.Checked) then alpha := alpha / (NoToAnalyze - 1);
Bonferroni := inversez(1.0 - alpha);
outline := format('significance level used for comparisons := %8.3f',[Bonferroni]);
OutputFrm.RichEdit.Lines.Add(outline);
Bonferroni := InverseZ(1.0 - alpha);
AReport.Add('Significance level used for comparisons: %8.3f', [Bonferroni]);
AReport.Add('');
for i := 0 to NoToAnalyze - 1 do
begin
if (i <> RefCol) then
begin
if (abs(Cratios[i]) > Bonferroni) then
begin
outline := format('%s vs %s significant',[ColLabels[i],ColLabels[RefCol]]);
OutputFrm.RichEdit.Lines.Add(outline);
end
AReport.Add('%s vs %s: significant', [ColLabels[i], ColLabels[RefCol]])
else
begin
outline := format('%s vs %s not significant',[ColLabels[i],ColLabels[RefCol]]);
OutPutFrm.RichEdit.Lines.Add(outline);
AReport.Add('%s vs %s: not significant', [ColLabels[i], ColLabels[RefCol]]);
end;
end;
end;
OutputFrm.ShowModal;
OutputFrm.RichEdit.Clear;
// cleanup
StdErr := nil;
@ -726,6 +716,20 @@ begin
probdists := nil;
end;
procedure TRIDITFrm.VarListSelectionChange(Sender: TObject; User: boolean);
begin
UpdateBtnStates;
end;
procedure TRIDITFrm.UpdateBtnStates;
begin
RowIn.Enabled := (VarList.ItemIndex > -1) and (RowEdit.Text = '');
RowOut.Enabled := (RowEdit.Text <> '');
ColIn.Enabled := AnySelected(VarList);
ColOut.Enabled := (ColList.ItemIndex > -1);
end;
initialization
{$I riditunit.lrs}

View File

@ -8,7 +8,7 @@ uses
Classes, SysUtils, Globals, DictionaryUnit, OutputUnit, Dialogs,
FunctionsLib, DataProcs, MainUnit;
procedure GridDotProd(col1, col2: integer; var Product: double; var Ngood: integer);
procedure GridDotProd(col1, col2: integer; out Product: double; var Ngood: integer);
procedure GridXProd(NoSelected : integer;
{VAR} Selected : IntDyneVec;
@ -199,9 +199,13 @@ procedure DynIntMatPrint(Mat: IntDyneMat; Rows, Cols: integer; YTitle: string;
procedure SymMatRoots(A : DblDyneMat; M : integer; VAR E : DblDyneVec; VAR V : DblDyneMat);
procedure matinv(a, vtimesw, v, w: DblDyneMat; n: integer);
implementation
procedure GridDotProd(col1, col2: integer; var Product: double; var Ngood: integer);
uses
StrUtils;
procedure GridDotProd(col1, col2: integer; out Product: double; var Ngood: integer);
// Get the cross-product of two vectors
// col1 and col2 are grid columns of the main form's DataGrid
// Product is the vector product
@ -1540,11 +1544,11 @@ begin
while not done do
begin
AReport.Add('');
// AReport.Add('');
AReport.Add(' ' + ytitle);;
AReport.Add('Variables');
outline := ' ';
outline := DupeString(' ', 12+1);
last := first + nflds;
if last >= cols then
begin
@ -1552,21 +1556,21 @@ begin
last := cols
end;
for i := first to last do
outline := outline + Format('%13s', [ColLabels[i-1]]);
outline := outline + Format('%12s ', [ColLabels[i-1]]);
AReport.Add(outline);
for i := 1 to rows do
begin
outline := format('%10s', [RowLabels[i-1]]);
outline := Format('%12s ', [RowLabels[i-1]]);
for j := first to last do
outline := outline + Format('%12d ',[mat[i-1,j-1]]);
AReport.Add(outline);
end;
AReport.Add('');
first := last + 1
first := last + 1;
end;
AReport.Add('');
AReport.Add('');
// AReport.Add('');
end;
//---------------------------------------------------------------------------
@ -1860,7 +1864,7 @@ begin
while not done do
begin
AReport.Add('Variables');
outline := ' ';
outline := DupeString(' ', 12+1); //' ';
last := first + nflds;
if last >= cols then
begin
@ -1873,7 +1877,7 @@ begin
for i := 1 to rows do
begin
outline := format('%10s',[RowLabels[i-1]]);
outline := format('%12s ',[RowLabels[i-1]]);
for j := first to last do
begin
valstring := format('%12.3f ',[xmat[i-1,j-1]]);
@ -1921,18 +1925,19 @@ begin
while not done do
begin
AReport.Add('');
outline := 'Variables';
last := first + nflds;
if last >= NoVars -1 then
begin
done := true;
last := NoVars-1;
end;
outline := 'Variables '; // 12+1 long
for i := first to last do
outline := outline + Format('%13s', [Labels[i]]);
outline := outline + Format('%12s ', [Labels[i]]);
AReport.Add(outline);
outline := ' ';
outline := DupeString(' ', 12+1); //' ';
for j := first to last do
begin
valstring := Format('%12.3f ', [AVector[j]]);
@ -1955,10 +1960,11 @@ procedure scatplot(var x : DblDyneVec;
var
i, j, l, row, xslot : integer;
xdelta, maxy: double;
//xdelta: Double;
maxy: double;
incrementx, incrementy, rangex, rangey, swap : double;
plotstring : array[0..51,0..61] of char;
ymed, xmed : double;
//ymed, xmed : double;
height : integer;
overlap : boolean;
valuestring : string[2];
@ -1973,11 +1979,11 @@ begin
height := 40;
rangex := x_max - x_min ;
incrementx := rangex / 15.0;
xdelta := rangex / 60;
xmed := rangex / 2;
// xdelta := rangex / 60;
// xmed := rangex / 2;
rangey := y_max - y_min;
incrementy := rangey / height;
ymed := rangey / 2;
// ymed := rangey / 2;
{ sort in descending order }
for i := 1 to (nocases - 1) do