LazStats: Imoproved results presentation in RIDITUnit.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7830 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-10-31 11:31:29 +00:00
parent aac25fbe8d
commit 151ba06d69
2 changed files with 225 additions and 101 deletions

View File

@ -1,13 +1,13 @@
inherited RIDITForm: TRIDITForm
Left = 778
Left = 864
Height = 477
Top = 182
Width = 673
Top = 327
Width = 903
HelpType = htKeyword
HelpKeyword = 'html/RIDITAnalysis.htm'
Caption = 'Relative to an Identified Distribution Analysis'
ClientHeight = 477
ClientWidth = 673
ClientWidth = 903
inherited ParamsPanel: TPanel
Height = 461
Width = 416
@ -408,4 +408,30 @@ inherited RIDITForm: TRIDITForm
Left = 428
Height = 477
end
object PageControl: TPageControl[2]
Left = 437
Height = 461
Top = 8
Width = 458
ActivePage = FrequenciesPage
Align = alClient
BorderSpacing.Left = 4
BorderSpacing.Top = 8
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
TabIndex = 1
TabOrder = 2
object ResultsPage: TTabSheet
Caption = 'Results'
end
object FrequenciesPage: TTabSheet
Caption = 'Frequencies'
end
object RowColPropsPage: TTabSheet
Caption = 'Row/Column Properties'
end
object CellChiSqrPage: TTabSheet
Caption = 'Cell ChiSsqr'
end
end
end

View File

@ -6,8 +6,8 @@ interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
StdCtrls, Buttons, ExtCtrls,
MainUnit, Globals, FunctionsLib, MatrixLib, BasicStatsReportFormUnit;
StdCtrls, Buttons, ExtCtrls, ComCtrls,
MainUnit, Globals, FunctionsLib, MatrixLib, ReportFrameUnit, BasicStatsReportFormUnit;
type
@ -17,6 +17,7 @@ type
Bevel2: TBevel;
BonChk: TCheckBox;
AlphaEdit: TEdit;
PageControl: TPageControl;
Panel1: TPanel;
AlphaLabel: TLabel;
ObsChk: TCheckBox;
@ -24,6 +25,10 @@ type
PropChk: TCheckBox;
ChiChk: TCheckBox;
RefGrp: TRadioGroup;
ResultsPage: TTabSheet;
FrequenciesPage: TTabSheet;
RowColPropsPage: TTabSheet;
CellChiSqrPage: TTabSheet;
YatesChk: TCheckBox;
DetailsChk: TCheckBox;
ColList: TListBox;
@ -46,15 +51,18 @@ type
procedure RefGrpClick(Sender: TObject);
procedure RowInClick(Sender: TObject);
procedure RowOutClick(Sender: TObject);
procedure Analyze(RefCol: integer; ColNoSelected: IntDyneVec;
RowLabels: StrDyneVec; ColLabels: StrDyneVec;
NoToAnalyze: integer; Freq: IntDyneMat;
Props: DblDyneMat; NoRows: integer; AReport: TStrings);
procedure VarListDblClick(Sender: TObject);
procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean);
private
FFrequenciesReportFrame: TReportFrame;
FRowColPropsReportFrame: TReportFrame;
FCellChiSqrReportFrame: TReportFrame;
procedure Analyze(RefCol: integer; RowLabels, ColLabels: StrDyneVec;
NoToAnalyze: integer; Freq: IntDyneMat; Props: DblDyneMat;
NoRows: integer; AReport: TStrings);
protected
procedure AdjustConstraints; override;
procedure Compute; override;
@ -62,6 +70,7 @@ type
function Validate(out AMsg: String; out AControl: TWinControl): Boolean; override;
public
constructor Create(AOwner: TComponent); override;
procedure Reset; override;
end;
@ -79,6 +88,46 @@ uses
{ TRIDITForm }
constructor TRIDITForm.Create(AOwner: TComponent);
begin
inherited;
FReportFrame.Parent := ResultsPage;
FFrequenciesReportFrame := TReportFrame.Create(self);
FFrequenciesReportFrame.Name := '';
FFrequenciesReportFrame.Parent := FrequenciesPage;
FFrequenciesReportFrame.Align := alClient;
FFrequenciesReportFrame.BorderSpacing.Left := 0;
FFrequenciesReportFrame.BorderSpacing.Top := 0;
FFrequenciesReportFrame.BorderSpacing.Bottom := 0;
FFrequenciesReportFrame.BorderSpacing.Right := 0;
InitToolbar(FFrequenciesReportFrame.ReportToolbar, tpRight);
FRowColPropsReportFrame := TReportFrame.Create(self);
FRowColPropsReportFrame.Name := '';
FRowColPropsReportFrame.Parent := RowColPropsPage;
FRowColPropsReportFrame.Align := alClient;
FRowColPropsReportFrame.BorderSpacing.Left := 0;
FRowColPropsReportFrame.BorderSpacing.Top := 0;
FRowColPropsReportFrame.BorderSpacing.Bottom := 0;
FRowColPropsReportFrame.BorderSpacing.Right := 0;
InitToolbar(FRowColPropsReportFrame.ReportToolbar, tpRight);
FCellChiSqrReportFrame := TReportFrame.Create(self);
FCellChiSqrReportFrame.Name := '';
FCellChiSqrReportFrame.Parent := CellChiSqrPage;
FCellChiSqrReportFrame.Align := alClient;
FCellChiSqrReportFrame.BorderSpacing.Left := 0;
FCellChiSqrReportFrame.BorderSpacing.Top := 0;
FCellChiSqrReportFrame.BorderSpacing.Bottom := 0;
FCellChiSqrReportFrame.BorderSpacing.Right := 0;
InitToolbar(FCellChiSqrReportFrame.ReportToolbar, tpRight);
PageControl.ActivePageIndex := 0;
end;
procedure TRIDITForm.AdjustConstraints;
begin
inherited;
@ -95,11 +144,9 @@ begin
end;
procedure TRIDITForm.Analyze(RefCol : integer; ColNoSelected : IntDyneVec;
RowLabels : StrDyneVec; ColLabels : StrDyneVec;
NoToAnalyze : integer; Freq : IntDyneMat;
Props : DblDyneMat; NoRows : integer;
AReport: TStrings);
procedure TRIDITForm.Analyze(RefCol: integer; RowLabels, ColLabels: StrDyneVec;
NoToAnalyze: integer; Freq: IntDyneMat; Props: DblDyneMat; NoRows: integer;
AReport: TStrings);
var
probdists : DblDyneMat = nil;
refprob : DblDyneMat = nil;
@ -218,10 +265,13 @@ begin
DynVectorPrint(Cratios, NoToAnalyze, outline, ColLabels, NoCases, AReport);
alpha := alpha / 2.0;
if (BonChk.Checked) then alpha := alpha / (NoToAnalyze - 1);
Bonferroni := InverseZ(1.0 - alpha);
AReport.Add('Significance level used for comparisons: %8.3f', [Bonferroni]);
AReport.Add('');
if BonChk.Checked then
begin
alpha := alpha / (NoToAnalyze - 1);
Bonferroni := InverseZ(1.0 - alpha);
AReport.Add('Significance level used for comparisons: %8.3f', [Bonferroni]);
AReport.Add('');
end;
for i := 0 to NoToAnalyze - 1 do
if (i <> RefCol) then
@ -312,7 +362,6 @@ var
AllRefs : boolean;
i, j, RowNo, RefColNo, NoToAnalyze : integer;
Row, Col, Ncases, Nrows, Ncols, df : integer;
outline : string;
ChiSquare, ProbChi : double;
yates : boolean;
Adjchisqr, Adjprobchi: double;
@ -349,8 +398,7 @@ begin
ColNoSelected[i+1] := GetVariableIndex(OS3MainFrm.DataGrid, ColLabels[i]);
end;
// allocate and initialize
// Allocate and initialize
SetLength(Freq, NRows+1, NCols+1);
SetLength(Prop, NRows+1, NCols+1);
SetLength(Expected, NRows, NCols);
@ -361,7 +409,7 @@ begin
RowLabels[NRows] := 'Total';
ColLabels[NCols] := 'Total';
// get cell data
// Get cell data
NCases := 0;
for i := 1 to NoCases do
begin
@ -393,14 +441,15 @@ begin
// Then get expected values and cell chi-squares
ChiSquare := 0.0;
Adjchisqr := 0.0;
yates := YatesChk.Checked and (Nrows = 2) and (Ncols = 2);
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
for i := 1 to NRows do
begin
for j := 1 to Ncols do
for j := 1 to NCols do
begin
Expected[i-1,j-1] := Freq[Nrows,j-1] * Freq[i-1,Ncols] / Ncases;
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]
else
@ -411,22 +460,22 @@ begin
ChiSquare := ChiSquare + CellChi[i-1,j-1];
end;
end;
df := (Nrows - 1) * (Ncols - 1);
df := (NRows - 1) * (NCols - 1);
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
AdjChiSqr := sqr(AdjChiSqr - NCases / 2.0) * NCases; // numerator
AdjChiSqr := AdjChiSqr / (Freq[0,2] * Freq[1,2] * Freq[2,0] * Freq[2,1]);
AdjProbChi := 1.0 - chisquaredprob(AdjChiSqr,df);
AdjProbChi := 1.0 - ChiSquaredProb(AdjChiSqr, df);
end;
end;
if (Nrows = 1) then // equal probability
if (NRows = 1) then // equal probability
begin
for j := 0 to Ncols - 1 do
for j := 0 to NCols - 1 do
begin
Expected[0,j] := Ncases / Ncols;
Expected[0,j] := NCases / NCols;
if (Expected[0][j] > 0) then
CellChi[0,j] := sqr(Freq[0,j] - Expected[0,j]) / Expected[0,j];
ChiSquare := ChiSquare + CellChi[0,j];
@ -434,7 +483,7 @@ begin
df := Ncols - 1;
end;
if (Ncols = 1) then // equal probability
if (NCols = 1) then // equal probability
begin
for i := 0 to Nrows - 1 do
begin
@ -448,70 +497,99 @@ begin
ProbChi := 1.0 - ChiSquaredProb(ChiSquare, df); // prob. larger chi
//Print results to output form
// Print results to output form
lReport := TStringList.Create;
try
// Print frequencies tables if requested by user
if ObsChk.Checked or ExpChk.Checked then
begin
FrequenciesPage.TabVisible := true;
lReport.Add('CHI-SQUARE ANALYSIS RESULTS');
lReport.Add('No. of Cases: %d', [Ncases]);
if ObsChk.Checked then
begin
IntArrayPrint(Freq, NRows+1, NCols+1, 'Frequencies', RowLabels, ColLabels, 'OBSERVED FREQUENCIES', lReport);
if ExpChk.Checked then
begin
lReport.Add(DIVIDER_SMALL_AUTO);
lReport.Add('');
end;
end;
if ExpChk.Checked then
MatPrint(Expected, Nrows, Ncols, 'EXPECTED FREQUENCIES', RowLabels, ColLabels, NoCases, lReport);
FFrequenciesReportFrame.DisplayReport(lReport);
lReport.Clear;
end else
FrequenciesPage.TabVisible := false;
// Print row/col properties
if PropChk.Checked then
begin
RowColPropsPage.TabVisible := true;
lReport.Add('CHI-SQUARE ANALYSIS RESULTS');
lReport.Add('No. of Cases: %d', [Ncases]);
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;
end;
if (Freq[i-1,NCols] > 0.0) then
Prop[i-1,NCols] := 1.0
else
Prop[i-1,NCols] := 0.0;
end;
MatPrint(Prop, Nrows+1, Ncols+1, 'ROW PROPORTIONS', RowLabels, ColLabels, NoCases, lReport);
lReport.Add(DIVIDER_SMALL_AUTO);
lReport.Add('');
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;
end;
if (Freq[Nrows,j-1] > 0.0) then
Prop[Nrows,j-1] := 1.0
else
Prop[Nrows,j-1] := 0.0;
end;
MatPrint(Prop, Nrows+1, Ncols+1, 'COLUMN PROPORTIONS', RowLabels, ColLabels, NoCases, lReport);
FRowColPropsReportFrame.DisplayReport(lReport);
lReport.Clear;
end else
RowColPropsPage.TabVisible := false;
// Print cell chi-sqr values if requested by user
if ChiChk.Checked then
begin
CellChiSqrPage.TabVisible := true;
lReport.Add('CHI-SQUARE ANALYSIS RESULTS');
lReport.Add('No. of Cases: %d', [Ncases]);
MatPrint(CellChi, Nrows, Ncols, 'CHI-SQUARED VALUE FOR CELLS', RowLabels, ColLabels, NoCases, lReport);
FCellChiSqrReportFrame.DisplayReport(lReport);
lReport.Clear;
end else
CellChiSqrPage.TabVisible := false;
lReport.Add('CHI-SQUARE ANALYSIS RESULTS');
lReport.Add('No. of Cases: %d', [Ncases]);
lReport.Add('');
// print tables requested by use
if ObsChk.Checked then
IntArrayPrint(Freq, Nrows+1, Ncols+1, 'Frequencies', RowLabels, ColLabels, 'OBSERVED FREQUENCIES', lReport);
if ExpChk.Checked then
begin
outline := 'EXPECTED FREQUENCIES';
MatPrint(Expected, Nrows, Ncols, outline, RowLabels, ColLabels, NoCases, lReport);
end;
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;
end;
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
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;
end;
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
begin
outline := 'COLUMN PROPORTIONS';
MatPrint(Prop, Nrows+1, Ncols+1, outline, RowLabels, ColLabels, NoCases, lReport);
end;
if ChiChk.Checked then
begin
outline := 'CHI-SQUARED VALUE FOR CELLS';
MatPrint(CellChi, Nrows, Ncols, outline, RowLabels, ColLabels, NoCases, lReport);
end;
lReport.Add('');
lReport.Add( 'Chi-square: %8.3f', [ChiSquare]);
lReport.Add( ' with D.F. %8d', [df]);
@ -539,7 +617,6 @@ begin
begin
phi := sqrt(ChiSquare / Ncases);
lReport.Add('phi correlation: %8.4f', [phi]);
lReport.Add('');
pearsonr := 0.0;
SumX := 0.0;
@ -558,16 +635,13 @@ begin
pearsonr := pearsonr - (SumX * SumY / Ncases);
pearsonr := pearsonr / sqrt(VarX * VarY);
lReport.Add('Pearson Correlation r: %8.4f', [pearsonr]);
lReport.Add('');
MantelHaenszel := (Ncases-1) * (pearsonr * pearsonr);
MHprob := 1.0 - chisquaredprob(MantelHaenszel,1);
lReport.Add('Mantel-Haenszel Test of Linear Association: %.3f with probability > value %.4f', [MantelHaenszel, MHprob]);
lReport.Add('');
CoefCont := sqrt(ChiSquare / (ChiSquare + Ncases));
lReport.Add('The coefficient of contingency: %8.3f', [CoefCont]);
lReport.Add('');
if (Nrows < Ncols) then
CramerV := sqrt(ChiSquare / (Ncases * ((Nrows-1))))
@ -577,7 +651,7 @@ begin
end;
lReport.Add('');
lReport.Add('=============================================================================');
lReport.Add(DIVIDER_AUTO);
lReport.Add('');
// Now do RIDIT analysis
@ -590,7 +664,13 @@ begin
for i := 0 to NoToAnalyze - 1 do
begin
RefColNo := ColNoSelected[i+1] - 2;
Analyze(RefColNo, ColNoSelected, RowLabels,ColLabels, NoToAnalyze, Freq, Prop, Nrows, lReport);
Analyze(RefColNo, RowLabels,ColLabels, NoToAnalyze, Freq, Prop, Nrows, lReport);
if i < NoToAnalyze-1 then
begin
lReport.Add('');
lReport.Add(DIVIDER_SMALL_AUTO);
lReport.Add('');
end;
end;
end else
// only one selected reference variable
@ -603,7 +683,7 @@ begin
for j := 0 to NoToAnalyze - 1 do
if (ColNoSelected[j+1] = RefColNo) then RefColNo := j;
Analyze(RefColNo, ColNoSelected, RowLabels,ColLabels, NoToAnalyze, Freq, Prop, Nrows, lReport);
Analyze(RefColNo, RowLabels,ColLabels, NoToAnalyze, Freq, Prop, Nrows, lReport);
end;
FReportFrame.DisplayReport(lReport);
@ -627,6 +707,17 @@ var
begin
inherited;
FrequenciesPage.TabVisible := false;
RowColPropsPage.TabVisible := false;
CellChiSqrPage.TabVisible := false;
if FFrequenciesReportFrame <> nil then
FFrequenciesReportFrame.Clear;
if FRowColPropsReportFrame <> nil then
FRowColPropsReportframe.Clear;
if FCellChiSqrReportFrame <> nil then
FCellChiSqrReportFrame.Clear;
VarList.Clear;
for i := 1 to NoVariables do
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
@ -671,7 +762,14 @@ end;
procedure TRIDITForm.UpdateBtnStates;
begin
inherited;
if FFrequenciesReportFrame <> nil then
FFrequenciesReportFrame.UpdateBtnStates;
if FRowColPropsReportFrame <> nil then
FRowColPropsReportframe.UpdateBtnStates;
if FCellChiSqrReportFrame <> nil then
FCellChiSqrReportFrame.UpdateBtnStates;
RowIn.Enabled := (VarList.ItemIndex > -1) and (RowEdit.Text = '');
RowOut.Enabled := (RowEdit.Text <> '');