You've already forked lazarus-ccr
Lazstats: Massive refactoring of DescriptiveUnits: Move calculation to new TDescriptiveStats class. More user-friendly interface.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7730 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -1558,11 +1558,6 @@
|
|||||||
<DebugInfoType Value="dsDwarf2"/>
|
<DebugInfoType Value="dsDwarf2"/>
|
||||||
</Debugging>
|
</Debugging>
|
||||||
<LinkSmart Value="True"/>
|
<LinkSmart Value="True"/>
|
||||||
<Options>
|
|
||||||
<Win32>
|
|
||||||
<GraphicApplication Value="True"/>
|
|
||||||
</Win32>
|
|
||||||
</Options>
|
|
||||||
</Linking>
|
</Linking>
|
||||||
</CompilerOptions>
|
</CompilerOptions>
|
||||||
<Debugging>
|
<Debugging>
|
||||||
|
@ -1,37 +1,45 @@
|
|||||||
inherited DescriptiveFrm: TDescriptiveFrm
|
inherited DescriptiveFrm: TDescriptiveFrm
|
||||||
Left = 526
|
Left = 526
|
||||||
Height = 384
|
Height = 432
|
||||||
Top = 202
|
Top = 202
|
||||||
Width = 900
|
Width = 900
|
||||||
HelpType = htKeyword
|
HelpType = htKeyword
|
||||||
HelpKeyword = 'html/DistributionStatistics.htm'
|
HelpKeyword = 'html/DistributionStatistics.htm'
|
||||||
Caption = 'Descriptive Statistics'
|
Caption = 'Descriptive Statistics'
|
||||||
ClientHeight = 384
|
ClientHeight = 432
|
||||||
ClientWidth = 900
|
ClientWidth = 900
|
||||||
inherited ParamsPanel: TPanel
|
inherited ParamsPanel: TPanel
|
||||||
Left = 16
|
Left = 16
|
||||||
Height = 352
|
Height = 400
|
||||||
Top = 16
|
Top = 16
|
||||||
Width = 322
|
Width = 322
|
||||||
BorderSpacing.Around = 8
|
BorderSpacing.Around = 8
|
||||||
ClientHeight = 352
|
ClientHeight = 400
|
||||||
ClientWidth = 322
|
ClientWidth = 322
|
||||||
inherited CloseBtn: TButton
|
inherited CloseBtn: TButton
|
||||||
|
Left = 267
|
||||||
|
Top = 375
|
||||||
TabOrder = 9
|
TabOrder = 9
|
||||||
end
|
end
|
||||||
inherited ComputeBtn: TButton
|
inherited ComputeBtn: TButton
|
||||||
AnchorSideBottom.Control = ParamsPanel
|
AnchorSideBottom.Control = ParamsPanel
|
||||||
AnchorSideBottom.Side = asrBottom
|
AnchorSideBottom.Side = asrBottom
|
||||||
|
Left = 184
|
||||||
|
Top = 375
|
||||||
TabOrder = 10
|
TabOrder = 10
|
||||||
end
|
end
|
||||||
inherited ResetBtn: TButton
|
inherited ResetBtn: TButton
|
||||||
|
Left = 122
|
||||||
|
Top = 375
|
||||||
TabOrder = 8
|
TabOrder = 8
|
||||||
end
|
end
|
||||||
inherited HelpBtn: TButton
|
inherited HelpBtn: TButton
|
||||||
|
Left = 63
|
||||||
|
Top = 375
|
||||||
TabOrder = 7
|
TabOrder = 7
|
||||||
end
|
end
|
||||||
inherited ButtonBevel: TBevel
|
inherited ButtonBevel: TBevel
|
||||||
Top = 311
|
Top = 359
|
||||||
Width = 322
|
Width = 322
|
||||||
end
|
end
|
||||||
object Label2: TLabel[5]
|
object Label2: TLabel[5]
|
||||||
@ -51,7 +59,7 @@ inherited DescriptiveFrm: TDescriptiveFrm
|
|||||||
AnchorSideRight.Control = AllBtn
|
AnchorSideRight.Control = AllBtn
|
||||||
AnchorSideBottom.Control = OptionsGroup
|
AnchorSideBottom.Control = OptionsGroup
|
||||||
Left = 0
|
Left = 0
|
||||||
Height = 183
|
Height = 202
|
||||||
Top = 17
|
Top = 17
|
||||||
Width = 130
|
Width = 130
|
||||||
Anchors = [akTop, akLeft, akRight, akBottom]
|
Anchors = [akTop, akLeft, akRight, akBottom]
|
||||||
@ -84,7 +92,7 @@ inherited DescriptiveFrm: TDescriptiveFrm
|
|||||||
AnchorSideBottom.Control = VarList
|
AnchorSideBottom.Control = VarList
|
||||||
AnchorSideBottom.Side = asrBottom
|
AnchorSideBottom.Side = asrBottom
|
||||||
Left = 192
|
Left = 192
|
||||||
Height = 183
|
Height = 202
|
||||||
Top = 17
|
Top = 17
|
||||||
Width = 130
|
Width = 130
|
||||||
Anchors = [akTop, akLeft, akRight, akBottom]
|
Anchors = [akTop, akLeft, akRight, akBottom]
|
||||||
@ -149,7 +157,7 @@ inherited DescriptiveFrm: TDescriptiveFrm
|
|||||||
AnchorSideRight.Control = CIEdit
|
AnchorSideRight.Control = CIEdit
|
||||||
Left = 0
|
Left = 0
|
||||||
Height = 15
|
Height = 15
|
||||||
Top = 292
|
Top = 311
|
||||||
Width = 174
|
Width = 174
|
||||||
BorderSpacing.Right = 8
|
BorderSpacing.Right = 8
|
||||||
Caption = 'Confidence Interval for the Mean'
|
Caption = 'Confidence Interval for the Mean'
|
||||||
@ -161,7 +169,7 @@ inherited DescriptiveFrm: TDescriptiveFrm
|
|||||||
AnchorSideBottom.Control = CIEdit
|
AnchorSideBottom.Control = CIEdit
|
||||||
Left = 0
|
Left = 0
|
||||||
Height = 72
|
Height = 72
|
||||||
Top = 208
|
Top = 227
|
||||||
Width = 306
|
Width = 306
|
||||||
Anchors = [akLeft, akBottom]
|
Anchors = [akLeft, akBottom]
|
||||||
AutoSize = True
|
AutoSize = True
|
||||||
@ -197,7 +205,7 @@ inherited DescriptiveFrm: TDescriptiveFrm
|
|||||||
Caption = 'z Scores to Grid'
|
Caption = 'z Scores to Grid'
|
||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
end
|
end
|
||||||
object PcntileChk: TCheckBox
|
object PercentileChk: TCheckBox
|
||||||
AnchorSideTop.Side = asrBottom
|
AnchorSideTop.Side = asrBottom
|
||||||
Left = 12
|
Left = 12
|
||||||
Height = 19
|
Height = 19
|
||||||
@ -208,7 +216,7 @@ inherited DescriptiveFrm: TDescriptiveFrm
|
|||||||
Caption = 'Show Percentile Ranks'
|
Caption = 'Show Percentile Ranks'
|
||||||
TabOrder = 2
|
TabOrder = 2
|
||||||
end
|
end
|
||||||
object AllQrtilesChk: TCheckBox
|
object AllQuartilesChk: TCheckBox
|
||||||
AnchorSideTop.Side = asrBottom
|
AnchorSideTop.Side = asrBottom
|
||||||
Left = 174
|
Left = 174
|
||||||
Height = 19
|
Height = 19
|
||||||
@ -224,29 +232,66 @@ inherited DescriptiveFrm: TDescriptiveFrm
|
|||||||
AnchorSideLeft.Control = Label1
|
AnchorSideLeft.Control = Label1
|
||||||
AnchorSideLeft.Side = asrBottom
|
AnchorSideLeft.Side = asrBottom
|
||||||
AnchorSideRight.Side = asrBottom
|
AnchorSideRight.Side = asrBottom
|
||||||
|
AnchorSideBottom.Control = DecPlacesEdit
|
||||||
Left = 182
|
Left = 182
|
||||||
Height = 23
|
Height = 23
|
||||||
Top = 288
|
Top = 307
|
||||||
Width = 41
|
Width = 50
|
||||||
Alignment = taRightJustify
|
Alignment = taRightJustify
|
||||||
Anchors = [akLeft, akBottom]
|
Anchors = [akLeft, akBottom]
|
||||||
BorderSpacing.Left = 8
|
BorderSpacing.Left = 8
|
||||||
TabOrder = 6
|
TabOrder = 6
|
||||||
Text = '95.0'
|
Text = '95.0'
|
||||||
end
|
end
|
||||||
|
object DecPlacesEdit: TSpinEdit[15]
|
||||||
|
AnchorSideLeft.Control = CIEdit
|
||||||
|
AnchorSideTop.Side = asrBottom
|
||||||
|
AnchorSideRight.Control = CIEdit
|
||||||
|
AnchorSideRight.Side = asrBottom
|
||||||
|
AnchorSideBottom.Control = ButtonBevel
|
||||||
|
Left = 182
|
||||||
|
Height = 23
|
||||||
|
Top = 334
|
||||||
|
Width = 50
|
||||||
|
Alignment = taRightJustify
|
||||||
|
Anchors = [akLeft, akRight, akBottom]
|
||||||
|
BorderSpacing.Top = 4
|
||||||
|
BorderSpacing.Bottom = 2
|
||||||
|
MaxValue = 10
|
||||||
|
TabOrder = 11
|
||||||
|
Value = 3
|
||||||
|
end
|
||||||
|
object Label4: TLabel[16]
|
||||||
|
AnchorSideLeft.Control = Label1
|
||||||
|
AnchorSideTop.Control = DecPlacesEdit
|
||||||
|
AnchorSideTop.Side = asrCenter
|
||||||
|
Left = 0
|
||||||
|
Height = 15
|
||||||
|
Top = 338
|
||||||
|
Width = 79
|
||||||
|
Caption = 'Decimal places'
|
||||||
|
ParentColor = False
|
||||||
|
end
|
||||||
end
|
end
|
||||||
inherited ParamsSplitter: TSplitter
|
inherited ParamsSplitter: TSplitter
|
||||||
Left = 350
|
Left = 350
|
||||||
Height = 384
|
Height = 432
|
||||||
end
|
end
|
||||||
object ReportPanel: TPanel[2]
|
object PageControl: TPageControl[2]
|
||||||
Left = 355
|
Left = 359
|
||||||
Height = 384
|
Height = 416
|
||||||
Top = 0
|
Top = 8
|
||||||
Width = 545
|
Width = 533
|
||||||
|
ActivePage = ReportPage
|
||||||
Align = alClient
|
Align = alClient
|
||||||
Anchors = [akTop, akLeft, akRight]
|
BorderSpacing.Left = 4
|
||||||
BevelOuter = bvNone
|
BorderSpacing.Top = 8
|
||||||
|
BorderSpacing.Right = 8
|
||||||
|
BorderSpacing.Bottom = 8
|
||||||
|
TabIndex = 0
|
||||||
TabOrder = 2
|
TabOrder = 2
|
||||||
|
object ReportPage: TTabSheet
|
||||||
|
Caption = 'Report'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -6,23 +6,73 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
|
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
|
||||||
StdCtrls, ExtCtrls, Buttons,
|
StdCtrls, ExtCtrls, Buttons, Spin, ComCtrls, Grids,
|
||||||
MainUnit, Globals, FunctionsLib, BasicStatsReportFormUnit,
|
MainUnit, Globals, FunctionsLib, ReportFrameUnit, BasicStatsReportFormUnit,
|
||||||
DataProcs, DictionaryUnit;
|
DataProcs, DictionaryUnit;
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
{ TDescriptiveFrm }
|
{ TDescriptiveStats }
|
||||||
|
|
||||||
|
TDescriptiveOption = (doAlternativeQuartiles, doPercentileRanks, doCasewiseDeletion);
|
||||||
|
TDescriptiveOptions = set of TDescriptiveOption;
|
||||||
|
TQuartileMethod = 1..8;
|
||||||
|
TQuartile = 1..3;
|
||||||
|
|
||||||
|
TDescriptiveStats = class
|
||||||
|
private
|
||||||
|
FDataGrid: TStringGrid;
|
||||||
|
FColIndex: Integer;
|
||||||
|
FConfLevel: Double; // usually 0.95
|
||||||
|
FColsSelected: IntDyneVec;
|
||||||
|
FMean, FStdErrorMean, FDeltaMean: Double;
|
||||||
|
FMin, FMax: Double;
|
||||||
|
FSum: Double;
|
||||||
|
FVariance, FStdDev: Double;
|
||||||
|
FSkew, FStdErrorSkew: Double;
|
||||||
|
FKurtosis, FStdErrorKurtosis: Double;
|
||||||
|
FFirstQuartile, FMedian, FThirdQuartile: Double;
|
||||||
|
FCategoryValues, FPercentiles: DblDyneVec;
|
||||||
|
FFreqValues: IntDyneVec;
|
||||||
|
FOptions: TDescriptiveOptions;
|
||||||
|
FNumCases: Integer;
|
||||||
|
FQuartiles: array[TQuartileMethod, TQuartile] of Double;
|
||||||
|
procedure Calc_AlternativeQuartiles(const AValues: DblDyneVec);
|
||||||
|
function Calc_DeltaMean(AStdErrorOfMean: Double): Double;
|
||||||
|
procedure Calc_Moments(const AValues: DblDyneVec; AMean: Double;
|
||||||
|
out M2, M3, M4: Double);
|
||||||
|
procedure Calc_Quartiles(const AValues: DblDyneVec; out Q1, Median, Q3: Double);
|
||||||
|
procedure Calc_Skew_Kurtosis(StdDev, M2, M3, M4: Double; ANumCases: Integer;
|
||||||
|
out Skew, StdErrorSkew, Kurtosis, StdErrorKurtosis: Double);
|
||||||
|
procedure Calc_Sum_SumOfSquares_Min_Max(const AValues: DblDyneVec;
|
||||||
|
out ASum, ASumOfSquares, AMin, AMax: Double);
|
||||||
|
procedure CollectValues(out AValues: DblDyneVec);
|
||||||
|
procedure PercentileRank(const AValues: DblDyneVec;
|
||||||
|
out ACategoryValues, APercentiles: DblDyneVec; out AFreq: IntDyneVec);
|
||||||
|
public
|
||||||
|
constructor Create(ADataGrid: TStringGrid; AColsSelected: IntDyneVec; AConfLevel: Double);
|
||||||
|
procedure Analyze(AColIndex: Integer; AOptions: TDescriptiveOptions);
|
||||||
|
procedure WriteToReport(AVarName: String; ADecPlaces: Integer; AReport: TStrings);
|
||||||
|
property Mean: Double read FMean;
|
||||||
|
property StdDev: Double read FStdDev;
|
||||||
|
// more can be added...
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ TDescriptiveFrm }
|
||||||
|
|
||||||
TDescriptiveFrm = class(TBasicStatsReportForm)
|
TDescriptiveFrm = class(TBasicStatsReportForm)
|
||||||
CaseChk: TCheckBox;
|
CaseChk: TCheckBox;
|
||||||
|
DecPlacesEdit: TSpinEdit;
|
||||||
|
Label4: TLabel;
|
||||||
|
PageControl: TPageControl;
|
||||||
|
ReportPage: TTabSheet;
|
||||||
ZScoresToGridChk: TCheckBox;
|
ZScoresToGridChk: TCheckBox;
|
||||||
AllQrtilesChk: TCheckBox;
|
AllQuartilesChk: TCheckBox;
|
||||||
Label2: TLabel;
|
Label2: TLabel;
|
||||||
Label3: TLabel;
|
Label3: TLabel;
|
||||||
ReportPanel: TPanel;
|
PercentileChk: TCheckBox;
|
||||||
PcntileChk: TCheckBox;
|
|
||||||
OptionsGroup: TGroupBox;
|
OptionsGroup: TGroupBox;
|
||||||
InBtn: TBitBtn;
|
InBtn: TBitBtn;
|
||||||
OutBtn: TBitBtn;
|
OutBtn: TBitBtn;
|
||||||
@ -39,9 +89,9 @@ type
|
|||||||
procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean);
|
procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean);
|
||||||
|
|
||||||
private
|
private
|
||||||
{ private declarations }
|
function GetReportFrame(APageIndex: Integer): TReportFrame;
|
||||||
sum, variance, stddev, value, mean, min, max, range, skew, prob, df, CI : double;
|
procedure zScoresToGrid(AColIndex: Integer; const AColsSelected: IntDyneVec;
|
||||||
kurtosis, z, semean, seskew, sekurtosis, deviation, devsqr, M2, M3, M4 : double;
|
AMean, AStdDev: Double);
|
||||||
|
|
||||||
protected
|
protected
|
||||||
procedure AdjustConstraints; override;
|
procedure AdjustConstraints; override;
|
||||||
@ -49,6 +99,7 @@ type
|
|||||||
procedure UpdateBtnStates; override;
|
procedure UpdateBtnStates; override;
|
||||||
|
|
||||||
public
|
public
|
||||||
|
constructor Create(AOwner: TComponent); override;
|
||||||
procedure Reset; override;
|
procedure Reset; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -61,15 +112,381 @@ implementation
|
|||||||
{$R *.lfm}
|
{$R *.lfm}
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math;
|
Math,
|
||||||
|
Utils;
|
||||||
|
|
||||||
|
|
||||||
|
{===============================================================================
|
||||||
|
* TDescriptiveStats
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* TDescriptiveStats is a helper class which
|
||||||
|
* - does all the required calculations (Analyze) and
|
||||||
|
* - prepares the report for each variable (WriteToReport).
|
||||||
|
*==============================================================================}
|
||||||
|
|
||||||
|
constructor TDescriptiveStats.Create(ADataGrid: TStringGrid;
|
||||||
|
AColsSelected: IntDyneVec; AConfLevel: Double);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FDataGrid := ADataGrid;
|
||||||
|
FColsSelected := AColsSelected;
|
||||||
|
FConfLevel := AConfLevel;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDescriptiveStats.Analyze(AColIndex: Integer; AOptions: TDescriptiveOptions);
|
||||||
|
var
|
||||||
|
SS: Double;
|
||||||
|
values: DblDyneVec;
|
||||||
|
M2, M3, M4: Double;
|
||||||
|
begin
|
||||||
|
FMean := NaN;
|
||||||
|
FVariance := NaN;
|
||||||
|
FStdDev := NaN;
|
||||||
|
FStdErrorMean := NaN;
|
||||||
|
FDeltaMean := NaN;
|
||||||
|
FSkew := NaN;
|
||||||
|
FStdErrorSkew := NaN;
|
||||||
|
|
||||||
|
FColIndex := AColIndex;
|
||||||
|
FOptions := AOptions;
|
||||||
|
|
||||||
|
CollectValues(values);
|
||||||
|
FNumCases := Length(values);
|
||||||
|
|
||||||
|
SortOnX(values);
|
||||||
|
|
||||||
|
Calc_Sum_SumOfSquares_Min_Max(values, FSum, SS, FMin, FMax);
|
||||||
|
if FNumCases > 0 then begin
|
||||||
|
FMean := FSum / FNumCases;
|
||||||
|
if FNumCases > 1 then
|
||||||
|
begin
|
||||||
|
FVariance := (SS - sqr(FSum) / FNumCases) / (FNumCases - 1);
|
||||||
|
FStdDev := sqrt(FVariance);
|
||||||
|
FStdErrorMean := sqrt(FVariance / FNumCases);
|
||||||
|
FDeltaMean := Calc_DeltaMean(FStdErrorMean);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Calc_Moments(values, FMean, M2, M3, M4);
|
||||||
|
Calc_Skew_Kurtosis(FStdDev, M2, M3, M4, FNumCases, FSkew, FStdErrorSkew, FKurtosis, FStdErrorKurtosis);
|
||||||
|
|
||||||
|
Calc_Quartiles(values, FFirstQuartile, FMedian, FThirdQuartile);
|
||||||
|
|
||||||
|
if (doAlternativeQuartiles in FOptions) then
|
||||||
|
Calc_AlternativeQuartiles(values);
|
||||||
|
if (doPercentileRanks in FOptions) then
|
||||||
|
PercentileRank(values, FCategoryValues, FPercentiles, FFreqValues);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDescriptiveStats.Calc_AlternativeQuartiles(const AValues: DblDyneVec);
|
||||||
|
var
|
||||||
|
nCases: Integer;
|
||||||
|
q: TQuartile;
|
||||||
|
m: TQuartileMethod;
|
||||||
|
begin
|
||||||
|
nCases := Length(AValues);
|
||||||
|
for m := Low(TQuartileMethod) to High(TQuartileMethod) do
|
||||||
|
for q := Low(TQuartile) to High(TQuartile) do
|
||||||
|
FQuartiles[m, q] := Quartiles(m, 0.25*q, nCases, AValues);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
// Tolerance around the mean
|
||||||
|
function TDescriptiveStats.Calc_DeltaMean(AStdErrorOfMean: Double): Double;
|
||||||
|
var
|
||||||
|
alpha: Double;
|
||||||
|
confLev: Double;
|
||||||
|
DOF: Integer;
|
||||||
|
begin
|
||||||
|
alpha := (1 - FConfLevel) / 2;
|
||||||
|
confLev := 1 - alpha;
|
||||||
|
|
||||||
|
if FNumCases < 120 then
|
||||||
|
begin
|
||||||
|
DOF := FNumCases - 1;
|
||||||
|
Result := AStdErrorOfMean * InverseT(confLev, DOF);
|
||||||
|
end else
|
||||||
|
Result := AStdErrorOfMean * InverseZ(confLev);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDescriptiveStats.Calc_Moments(const AValues: DblDyneVec;
|
||||||
|
AMean: Double; out M2, M3, M4: Double);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
dev, devSqr: Double;
|
||||||
|
begin
|
||||||
|
M2 := 0;
|
||||||
|
M3 := 0;
|
||||||
|
M4 := 0;
|
||||||
|
for i := 0 to High(AValues) do
|
||||||
|
begin
|
||||||
|
dev := AValues[i] - AMean;
|
||||||
|
devSqr := Sqr(dev);
|
||||||
|
M2 := M2 + devSqr;
|
||||||
|
M3 := M3 + dev * devSqr;
|
||||||
|
M4 := M4 + sqr(devSqr);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDescriptiveStats.Calc_Quartiles(const AValues: DblDyneVec;
|
||||||
|
out Q1, Median, Q3: Double);
|
||||||
|
var
|
||||||
|
n: Integer;
|
||||||
|
begin
|
||||||
|
n := Length(AValues);
|
||||||
|
Q1 := Quartiles(2, 0.25, n, AValues);
|
||||||
|
Median := Quartiles(2, 0.5, n, AValues);
|
||||||
|
Q3 := Quartiles(2, 0.75, n, AValues);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDescriptiveStats.Calc_Skew_Kurtosis(StdDev, M2, M3, M4: Double;
|
||||||
|
ANumCases: Integer; out Skew, StdErrorSkew, Kurtosis, StdErrorKurtosis: Double);
|
||||||
|
var
|
||||||
|
num, denom: Double;
|
||||||
|
stdDev3, stdDev4: Double;
|
||||||
|
begin
|
||||||
|
Skew := NaN;
|
||||||
|
StdErrorSkew := NaN;
|
||||||
|
Kurtosis := NaN;
|
||||||
|
StdErrorKurtosis := NaN;
|
||||||
|
|
||||||
|
stdDev3 := StdDev * StdDev * StdDev;
|
||||||
|
stdDev4 := StdDev3 * StdDev;
|
||||||
|
|
||||||
|
if ANumCases > 2 then
|
||||||
|
begin
|
||||||
|
Skew := ANumCases * M3 / ((ANumCases - 1) * (ANumCases - 3) * stdDev3);
|
||||||
|
|
||||||
|
num := 6.0 * ANumCases * (ANumCases - 1);
|
||||||
|
denom := (ANumCases - 2) * (ANumCases + 1) * (ANumCases + 3);
|
||||||
|
StdErrorSkew := sqrt(num / denom);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if ANumCases > 3 then
|
||||||
|
begin
|
||||||
|
num := ANumCases * (ANumCases + 1) * M4 - 3 * M2 * M2 * (ANumCases - 1);
|
||||||
|
denom := (ANumCases - 1) * (ANumCases - 2) * (ANumCases - 3) * stdDev4;
|
||||||
|
Kurtosis := num / denom;
|
||||||
|
|
||||||
|
num := 4.0 * (sqr(ANumCases) - 1) * sqr(StdErrorSkew);
|
||||||
|
denom := (ANumCases - 3) * (ANumCases + 5);
|
||||||
|
StdErrorKurtosis := sqrt(num / denom);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDescriptiveStats.Calc_Sum_SumOfSquares_Min_Max(const AValues: DblDyneVec;
|
||||||
|
out ASum, ASumOfSquares, AMin, AMax: Double);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
ASum := 0.0;
|
||||||
|
ASumOfSquares := 0;
|
||||||
|
AMin := Infinity;
|
||||||
|
AMax := -Infinity;
|
||||||
|
|
||||||
|
for i := 0 to High(AValues) do
|
||||||
|
begin
|
||||||
|
ASum := ASum + AValues[i];
|
||||||
|
ASumOfSquares := ASumOfSquares + sqr(AValues[i]);
|
||||||
|
if AValues[i] < AMin then AMin := AValues[i];
|
||||||
|
if AValues[i] > AMax then AMax := AValues[i];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDescriptiveStats.CollectValues(out AValues: DblDyneVec);
|
||||||
|
var
|
||||||
|
i, n: Integer;
|
||||||
|
begin
|
||||||
|
AValues := nil; // silence the compiler
|
||||||
|
SetLength(AValues, NoCases);
|
||||||
|
n := 0;
|
||||||
|
for i := 1 to NoCases do
|
||||||
|
begin
|
||||||
|
if (doCasewiseDeletion in FOptions) then
|
||||||
|
begin
|
||||||
|
// Do not consider a case when any variable is empty
|
||||||
|
if not ValidValue(i, FColIndex) then
|
||||||
|
continue;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
// Do not consider a case when the current variable is empty
|
||||||
|
if not GoodRecord(i, Length(FColsSelected), FColsSelected) then
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if TryStrToFloat(FDataGrid.Cells[FColIndex, i], AValues[n]) then
|
||||||
|
inc(n)
|
||||||
|
else
|
||||||
|
raise Exception.CreateFmt('Invalid number: variable "%s", case "%s"',
|
||||||
|
[FDataGrid.cells[FColIndex, 0], FDataGrid.Cells[0, i]]);
|
||||||
|
end;
|
||||||
|
SetLength(AValues, n);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
// Computes the percentile ranks of values stored in the data grid at the
|
||||||
|
// loaded columns. The values are assumed to be sorted.
|
||||||
|
procedure TDescriptiveStats.PercentileRank(const AValues: DblDyneVec; out
|
||||||
|
ACategoryValues, APercentiles: DblDyneVec; out AFreq: IntDyneVec);
|
||||||
|
var
|
||||||
|
i, nCases, iCat, nCategories: Integer;
|
||||||
|
lastCategoryValue: Double;
|
||||||
|
cumFreqCentered: Double;
|
||||||
|
cumFreq: Integer;
|
||||||
|
begin
|
||||||
|
// silence the compiler
|
||||||
|
ACategoryvalues := nil;
|
||||||
|
AFreq := nil;
|
||||||
|
APercentiles := nil;
|
||||||
|
|
||||||
|
nCases := Length(AValues);
|
||||||
|
SetLength(ACategoryValues, nCases); // over-dimension; will be trimmed later
|
||||||
|
SetLength(AFreq, nCases);
|
||||||
|
|
||||||
|
// Get count of unique values and frequencies of each
|
||||||
|
lastCategoryValue := AValues[0];
|
||||||
|
ACategoryValues[0] := lastCategoryValue;
|
||||||
|
AFreq[0] := 1;
|
||||||
|
iCat := 0;
|
||||||
|
for i := 1 to nCases-1 do
|
||||||
|
begin
|
||||||
|
if (lastCategoryValue = AValues[i]) then
|
||||||
|
AFreq[iCat] := AFreq[iCat] + 1
|
||||||
|
else
|
||||||
|
begin // new value
|
||||||
|
inc(iCat);
|
||||||
|
AFreq[iCat] := 1;
|
||||||
|
lastCategoryValue := AValues[i];
|
||||||
|
ACategoryValues[iCat] := lastCategoryValue;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// trim arrays
|
||||||
|
nCategories := iCat + 1;
|
||||||
|
SetLength(ACategoryValues, nCategories);
|
||||||
|
SetLength(AFreq, nCategories);
|
||||||
|
|
||||||
|
// Get cumulative frequencies and percentile ranks
|
||||||
|
SetLength(APercentiles, nCategories);
|
||||||
|
APercentiles[0] := AFreq[0] * 0.5 / nCases;
|
||||||
|
cumFreq := AFreq[0];
|
||||||
|
for i := 1 to nCategories-1 do // NOTE: This loop must begin at index 1
|
||||||
|
begin
|
||||||
|
cumFreqCentered := cumFreq + AFreq[i]*0.5; // cum frequencies at mid-point
|
||||||
|
APercentiles[i] := cumFreqCentered / nCases;
|
||||||
|
cumFreq := cumFreq + AFreq[i];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDescriptiveStats.WriteToReport(AVarName: String; ADecPlaces: Integer;
|
||||||
|
AReport: TStrings);
|
||||||
|
var
|
||||||
|
w: Integer;
|
||||||
|
nCategories: Integer;
|
||||||
|
i: Integer;
|
||||||
|
cumFreq: Integer;
|
||||||
|
m: TQuartileMethod;
|
||||||
|
begin
|
||||||
|
w := 10 + ADecPlaces - 3;
|
||||||
|
AReport.Add('VARIABLE: %*s', [W, '"' + AVarName + '"']);
|
||||||
|
AReport.Add('');
|
||||||
|
AReport.Add('Number of cases: %*d', [W, FNumCases]);
|
||||||
|
AReport.Add('Sum: %*.*f', [W, ADecPlaces, FSum]);
|
||||||
|
AReport.Add('Mean: %*.*f', [W, ADecPlaces, FMean]);
|
||||||
|
AReport.Add('Variance: %*.*f', [W, ADecPlaces, FVariance]);
|
||||||
|
AReport.Add('Std.Dev.: %*.*f', [W, ADecPlaces, FStdDev]);
|
||||||
|
AReport.Add('Std.Error of Mean %*.*f', [W, ADecPlaces, FStdErrorMean]);
|
||||||
|
AReport.Add('%.2f%% Conf.Interval Mean: %.*f to %.*f', [
|
||||||
|
FConfLevel*100.0, ADecPlaces, FMean - FDeltaMean, ADecPlaces, FMean + FDeltaMean]);
|
||||||
|
AReport.Add('');
|
||||||
|
AReport.Add('Minimum: %*.*f', [W, ADecPlaces, FMin]);
|
||||||
|
AReport.Add('Maximum: %*.*f', [W, ADecPlaces, FMax]);
|
||||||
|
AReport.Add('Range: %*.*f', [W, ADecPlaces, FMax - FMin]);
|
||||||
|
AReport.Add('');
|
||||||
|
AReport.Add('Skewness: %*.*f', [W, ADecPlaces, FSkew]);
|
||||||
|
AReport.Add('Std.Error of Skew: %*.*f', [W, ADecPlaces, FStdErrorSkew]);
|
||||||
|
AReport.Add('Kurtosis: %*.*f', [W, ADecPlaces, FKurtosis]);
|
||||||
|
AReport.Add('Std. Error of Kurtosis: %*.*f', [W, ADecPlaces, FStdErrorKurtosis]);
|
||||||
|
AReport.Add('');
|
||||||
|
AReport.Add('First Quartile: %*.*f', [W, ADecPlaces, FFirstQuartile]);
|
||||||
|
AReport.Add('Median: %*.*f', [W, ADecPlaces, FMedian]);
|
||||||
|
AReport.Add('Third Quartile: %*.*f', [W, ADecPlaces, FThirdQuartile]);
|
||||||
|
AReport.Add('Interquartile range: %*.*f', [W, ADecPlaces, FThirdQuartile - FFirstQuartile]);
|
||||||
|
|
||||||
|
if (doAlternativeQuartiles in FOptions) then
|
||||||
|
begin
|
||||||
|
AReport.Add('');
|
||||||
|
AReport.Add('');
|
||||||
|
AReport.Add('ALTERNATIVE METHODS FOR OBTAINING QUARTILES');
|
||||||
|
AReport.Add('');
|
||||||
|
AReport.Add('Method First Quartile Median Third Quartile');
|
||||||
|
AReport.Add('------ -------------- ---------- --------------');
|
||||||
|
for m := Low(TQuartileMethod) to High(TQuartileMethod) do
|
||||||
|
AReport.Add(' %d %12.3f %12.3f %12.3f', [m, FQuartiles[m, 1], FQuartiles[m, 2], FQuartiles[m, 3]]);
|
||||||
|
AReport.Add('');
|
||||||
|
AReport.Add('NOTES:');
|
||||||
|
AReport.Add('Method 1 is the weighted average at X[np] where ');
|
||||||
|
AReport.Add(' n is no. of cases, p is percentile / 100');
|
||||||
|
AReport.Add('Method 2 is the weighted average at X[(n+1)p] This is used in this program.');
|
||||||
|
AReport.Add('Method 3 is the empirical distribution function.');
|
||||||
|
AReport.Add('Method 4 is called the empirical distribution function - averaging.');
|
||||||
|
AReport.Add('Method 5 is called the empirical distribution function = Interpolation.');
|
||||||
|
AReport.Add('Method 6 is the closest observation method.');
|
||||||
|
AReport.Add('Method 7 is from the TrueBasic Statistics Graphics Toolkit.');
|
||||||
|
AReport.Add('Method 8 was used in an older Microsoft Excel version.');
|
||||||
|
AReport.Add('See the internet site http://www.xycoon.com/ for the above.');
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (doPercentileRanks in FOptions) then
|
||||||
|
begin
|
||||||
|
nCategories := Length(FCategoryValues);
|
||||||
|
cumFreq := 0;
|
||||||
|
AReport.Add('');
|
||||||
|
AReport.Add('');
|
||||||
|
AReport.Add('PERCENTILE RANKS');
|
||||||
|
AReport.Add('');
|
||||||
|
AReport.Add('Score Value Frequency Cum.Freq. Percentile Rank');
|
||||||
|
AReport.Add('----------- --------- --------- ---------------');
|
||||||
|
for i := 0 to nCategories-1 do
|
||||||
|
begin
|
||||||
|
cumFreq := cumFreq + FFreqValues[i];
|
||||||
|
AReport.Add(' %8.3f %8d %8d %12.2f%%', [
|
||||||
|
FCategoryValues[i], FFreqValues[i], cumFreq, FPercentiles[i]*100.0
|
||||||
|
]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{ TDescriptiveFrm }
|
{ TDescriptiveFrm }
|
||||||
|
|
||||||
|
constructor TDescriptiveFrm.Create(AOwner: TComponent);
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
FReportFrame.Parent := ReportPage;
|
||||||
|
FReportFrame.BorderSpacing.Left := 0;
|
||||||
|
FReportFrame.BorderSpacing.Top := 0;
|
||||||
|
FReportFrame.BorderSpacing.Bottom := 0;
|
||||||
|
FReportFrame.BorderSpacing.Right := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TDescriptiveFrm.AdjustConstraints;
|
procedure TDescriptiveFrm.AdjustConstraints;
|
||||||
begin
|
begin
|
||||||
ParamsPanel.Constraints.MinHeight := AllBtn.Top + AllBtn.Height + OptionsGroup.Height +
|
ParamsPanel.Constraints.MinHeight := AllBtn.Top + AllBtn.Height + OptionsGroup.Height +
|
||||||
CIEdit.Height + ButtonBevel.Height + CloseBtn.Height + VarList.BorderSpacing.Bottom +
|
CIEdit.Height + ButtonBevel.Height + CloseBtn.Height + VarList.BorderSpacing.Bottom +
|
||||||
OptionsGroup.BorderSpacing.Bottom + CloseBtn.BorderSpacing.Top;
|
OptionsGroup.BorderSpacing.Bottom + CloseBtn.BorderSpacing.Top +
|
||||||
|
DecPlacesEdit.Height + DecPlacesEdit.BorderSpacing.Top;
|
||||||
|
|
||||||
ParamsPanel.Constraints.MinWidth := Math.Max(
|
ParamsPanel.Constraints.MinWidth := Math.Max(
|
||||||
4*CloseBtn.Width + 3*HelpBtn.BorderSpacing.Right,
|
4*CloseBtn.Width + 3*HelpBtn.BorderSpacing.Right,
|
||||||
OptionsGroup.Width
|
OptionsGroup.Width
|
||||||
@ -90,275 +507,100 @@ end;
|
|||||||
|
|
||||||
procedure TDescriptiveFrm.Compute;
|
procedure TDescriptiveFrm.Compute;
|
||||||
var
|
var
|
||||||
i, j, k, m: integer;
|
|
||||||
nCases, noSelected: integer;
|
|
||||||
Q1, Q2, Q3, Q12, Q13, Q14, Q15, Q16, Q17, Q18, Q22, Q23, Q24, Q25, Q26: double;
|
|
||||||
Q27, Q28, Q32, Q33, Q34, Q35, Q36, Q37, Q38, IQrange: double;
|
|
||||||
num, den, cases: double;
|
|
||||||
values: DblDyneVec = nil;
|
|
||||||
pcntRank: DblDyneVec = nil;
|
|
||||||
selected: IntDyneVec = nil;
|
|
||||||
cellString: String;
|
cellString: String;
|
||||||
|
i, j: Integer;
|
||||||
|
noSelected: Integer;
|
||||||
|
selected: IntDyneVec = nil;
|
||||||
|
page: TTabSheet;
|
||||||
|
reportFrame: TReportFrame;
|
||||||
lReport: TStrings;
|
lReport: TStrings;
|
||||||
|
lDescrStats: TDescriptiveStats;
|
||||||
|
options: TDescriptiveOptions;
|
||||||
begin
|
begin
|
||||||
NoSelected := SelList.Items.Count;
|
noSelected := SelList.Items.Count;
|
||||||
if noSelected = 0 then
|
if noSelected = 0 then
|
||||||
begin
|
begin
|
||||||
MessageDlg('No variables selected.', mtError, [mbOK], 0);
|
MessageDlg('No variables selected.', mtError, [mbOK], 0);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
SetLength(selected, noSelected);
|
SetLength(selected, noSelected);
|
||||||
|
|
||||||
// Get selected variables
|
// Find column index of selected variables
|
||||||
for i := 1 to noselected do
|
for i := 0 to noSelected - 1 do
|
||||||
begin
|
begin
|
||||||
cellstring := SelList.Items.Strings[i-1];
|
cellstring := SelList.Items[i];
|
||||||
for j := 1 to NoVariables do
|
for j := 1 to NoVariables do
|
||||||
if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then selected[i-1] := j;
|
if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then selected[i] := j;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Create a tabsheet with ReportFrame for each selected variable (in addition to the built-in one)
|
||||||
|
if noSelected > PageControl.PageCount then
|
||||||
|
begin
|
||||||
|
for i := 1 to noSelected-1 do // we do not create a tab for the first variable - it exists by default
|
||||||
|
begin
|
||||||
|
page := TTabSheet.Create(PageControl);
|
||||||
|
page.Parent := PageControl;
|
||||||
|
reportFrame := TReportFrame.Create(page);
|
||||||
|
reportFrame.Parent := page;
|
||||||
|
reportFrame.Align := alClient;
|
||||||
|
InitToolBar(reportFrame.ReportToolbar, tpRight);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Remove excess pages from previous session
|
||||||
|
while PageControl.PageCount > noSelected do
|
||||||
|
PageControl.Pages[PageControl.PageCount-1].Free;
|
||||||
|
|
||||||
|
// Every tab gets the name of the corresponding variable.
|
||||||
|
for i := 0 to NoSelected-1 do
|
||||||
|
PageControl.Pages[i].Caption := OS3MainFrm.DataGrid.Cells[selected[i], 0];
|
||||||
|
|
||||||
|
// Prepare options
|
||||||
|
options := [];
|
||||||
|
if PercentileChk.Checked then Include(options, doPercentileRanks);
|
||||||
|
if AllQuartilesChk.Checked then Include(options, doAlternativeQuartiles);
|
||||||
|
if CaseChk.Checked then Include(options, doCasewiseDeletion);
|
||||||
|
|
||||||
lReport := TStringList.Create;
|
lReport := TStringList.Create;
|
||||||
|
lDescrStats := TDescriptiveStats.Create(OS3MainFrm.DataGrid, selected, StrToFloat(CIEdit.Text)/100);
|
||||||
try
|
try
|
||||||
|
for i := 0 to noSelected-1 do
|
||||||
|
begin
|
||||||
|
// Analyze the data and get descriptive stats
|
||||||
|
lDescrStats.Analyze(selected[i], options);
|
||||||
|
|
||||||
|
// Store z values, (value - mean) / stdDev, to grid, if needed
|
||||||
|
zScoresToGrid(selected[i], selected, lDescrStats.Mean, lDescrStats.StdDev);
|
||||||
|
|
||||||
|
// Write descriptive stats to report
|
||||||
|
lReport.Clear;
|
||||||
lReport.Add('DISTRIBUTION PARAMETER ESTIMATES');
|
lReport.Add('DISTRIBUTION PARAMETER ESTIMATES');
|
||||||
lReport.Add('');
|
lReport.Add('');
|
||||||
|
lDescrStats.WriteToReport(trim(OS3MainFrm.DataGrid.Cells[selected[i], 0]),
|
||||||
|
DecPlacesEdit.Value, lReport);
|
||||||
|
|
||||||
SetLength(Values, NoCases);
|
// Display report in the page of the variable
|
||||||
SetLength(pcntRank, NoCases);
|
reportFrame := GetReportFrame(i);
|
||||||
|
reportFrame.DisplayReport(lReport);
|
||||||
for j := 1 to noSelected do
|
|
||||||
begin
|
|
||||||
deviation := 0.0;
|
|
||||||
devsqr := 0.0;
|
|
||||||
M2 := 0.0;
|
|
||||||
M3 := 0.0;
|
|
||||||
M4 := 0.0;
|
|
||||||
sum := 0.0;
|
|
||||||
variance := 0.0;
|
|
||||||
stddev := 0.0;
|
|
||||||
range := 0.0;
|
|
||||||
skew := 0.0;
|
|
||||||
kurtosis := 0.0;
|
|
||||||
ncases := 0;
|
|
||||||
df := 0.0;
|
|
||||||
seskew := 0.0;
|
|
||||||
kurtosis := 0.0;
|
|
||||||
sekurtosis := 0.0;
|
|
||||||
k := selected[j-1];
|
|
||||||
CI := StrToFloat(CIEdit.Text) / 100.0;
|
|
||||||
prob := CI;
|
|
||||||
CI := (1.0 - CI) / 2.0;
|
|
||||||
CI := 1.0 - CI;
|
|
||||||
|
|
||||||
if ZScoresToGridChk.Checked then // add a new column to the grid
|
|
||||||
begin
|
|
||||||
cellstring := OS3MainFrm.DataGrid.Cells[k,0] + 'z';
|
|
||||||
DictionaryFrm.NewVar(NoVariables + 1);
|
|
||||||
DictionaryFrm.DictGrid.Cells[1, NoVariables] := cellstring;
|
|
||||||
OS3MainFrm.DataGrid.Cells[NoVariables, 0] := cellstring;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Accumulate sums of squares, sums, etc. for variable j
|
|
||||||
min := 1.0e308;
|
|
||||||
max := -1.0e308;
|
|
||||||
for i := 1 to NoCases do
|
|
||||||
begin
|
|
||||||
if not GoodRecord(i, noSelected, selected) then
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if CaseChk.Checked then
|
|
||||||
begin
|
|
||||||
if not ValidValue(i, selected[j-1]) then
|
|
||||||
continue;
|
|
||||||
end
|
|
||||||
else if not GoodRecord(i, noselected, selected) then
|
|
||||||
continue;
|
|
||||||
|
|
||||||
value := StrToFloat(OS3MainFrm.DataGrid.Cells[k,i]);
|
|
||||||
ncases := ncases + 1;
|
|
||||||
values[ncases-1] := value;
|
|
||||||
df := df + 1.0;
|
|
||||||
sum := sum + value;
|
|
||||||
variance := variance + (value * value);
|
|
||||||
if (value < min) then min := value;
|
|
||||||
if (value > max) then max := value;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if ncases > 0 then
|
|
||||||
begin
|
|
||||||
mean := sum / ncases;
|
|
||||||
range := max - min;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if ncases > 1 then
|
|
||||||
begin
|
|
||||||
variance := variance - (sum * sum) / ncases;
|
|
||||||
variance := variance / (ncases - 1);
|
|
||||||
stddev := sqrt(variance);
|
|
||||||
semean := sqrt(variance / ncases);
|
|
||||||
if ncases < 120 then
|
|
||||||
CI := semean * inverset(CI,df)
|
|
||||||
else
|
|
||||||
CI := semean * inversez(CI);
|
|
||||||
end;
|
|
||||||
|
|
||||||
if variance = 0.0 then
|
|
||||||
begin
|
|
||||||
cellstring := OS3MainFrm.DataGrid.Cells[k,0];
|
|
||||||
MessageDlg('No Variability in '+ cellstring + ' variable - ending analysis.', mtInformation, [mbOK], 0);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if ncases > 3 then // obtain skew, kurtosis and z scores
|
|
||||||
begin
|
|
||||||
for i := 1 to NoCases do
|
|
||||||
begin
|
|
||||||
if CaseChk.Checked then
|
|
||||||
begin
|
|
||||||
if not ValidValue(i, selected[j-1]) then continue;
|
|
||||||
end else
|
|
||||||
if not GoodRecord(i, noselected, selected) then continue;
|
|
||||||
|
|
||||||
value := StrToFloat(OS3MainFrm.DataGrid.Cells[k,i]);
|
|
||||||
if stddev > 0.0 then
|
|
||||||
begin
|
|
||||||
deviation := value - mean;
|
|
||||||
devsqr := deviation * deviation;
|
|
||||||
M2 := M2 + devsqr;
|
|
||||||
M3 := M3 + (deviation * devsqr);
|
|
||||||
M4 := M4 + (devsqr * devsqr);
|
|
||||||
z := (value - mean) / stddev;
|
|
||||||
if ZScoresToGridChk.Checked then
|
|
||||||
begin
|
|
||||||
cellstring := format('%8.5f',[z]);
|
|
||||||
OS3MainFrm.DataGrid.Cells[NoVariables,i] := cellstring;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if ncases > 2 then
|
|
||||||
begin
|
|
||||||
skew := (ncases * M3) / ((ncases - 1) * (ncases - 2) * stddev * variance);
|
|
||||||
cases := ncases;
|
|
||||||
num := 6.0 * cases * (cases - 1.0);
|
|
||||||
den := (cases - 2.0) * (cases + 1.0) * (cases + 3.0);
|
|
||||||
seskew := sqrt(num / den);
|
|
||||||
end;
|
|
||||||
|
|
||||||
if ncases > 3 then
|
|
||||||
begin
|
|
||||||
kurtosis := (ncases * (ncases + 1) * M4) - (3 * M2 * M2 * (ncases - 1));
|
|
||||||
kurtosis := kurtosis / ( (ncases - 1) * (ncases - 2) * (ncases - 3) * (variance * variance) );
|
|
||||||
sekurtosis := sqrt((4.0 * (ncases * ncases - 1) * (seskew * seskew)) / ((ncases - 3) * (ncases + 5)));
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// output results for the kth variable
|
|
||||||
cellstring := OS3MainFrm.DataGrid.Cells[k,0];
|
|
||||||
if j > 1 then lReport.Add('');
|
|
||||||
lReport.Add('VARIABLE: %10s', ['"' + cellString + '"']);
|
|
||||||
lReport.Add('');
|
|
||||||
lReport.Add('Number of cases: %10d', [nCases]);
|
|
||||||
lReport.Add('Sum: %10.3f', [sum]);
|
|
||||||
lReport.Add('Mean: %10.3f', [mean]);
|
|
||||||
lReport.Add('Variance: %10.3f', [variance]);
|
|
||||||
lReport.Add('Std.Dev.: %10.3f', [stddev]);
|
|
||||||
lReport.Add('Std.Error of Mean %10.3f', [seMean]);
|
|
||||||
lReport.Add('%.2f%% Conf.Interval Mean: %10.3f to %.3f', [prob*100.0, mean - CI, mean + CI]);
|
|
||||||
lReport.Add('Range: %10.3f', [range]);
|
|
||||||
lReport.Add('Minimum: %10.3f', [min]);
|
|
||||||
lReport.Add('Maximum: %10.3f', [max]);
|
|
||||||
lReport.Add('Skewness: %10.3f', [skew]);
|
|
||||||
lReport.Add('Std.Error of Skew: %10.3f', [seSkew]);
|
|
||||||
lReport.Add('Kurtosis: %10.3f', [kurtosis]);
|
|
||||||
lReport.Add('Std. Error of Kurtosis: %10.3f', [seKurtosis]);
|
|
||||||
lReport.Add('');
|
|
||||||
|
|
||||||
if ncases > 4 then // get percentiles and quartiles
|
|
||||||
begin
|
|
||||||
// get percentile ranks
|
|
||||||
if pcntileChk.Checked then PRank(k, pcntRank, lReport);
|
|
||||||
|
|
||||||
// sort values and get quartiles
|
|
||||||
for i := 0 to ncases - 2 do
|
|
||||||
begin
|
|
||||||
for m := i + 1 to ncases -1 do
|
|
||||||
begin
|
|
||||||
if values[i] > values[m] then
|
|
||||||
begin
|
|
||||||
value := values[i];
|
|
||||||
values[i] := values[m];
|
|
||||||
values[m] := value;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
Q1 := Quartiles(2,0.25,ncases,values);
|
|
||||||
Q2 := Quartiles(2,0.5,ncases,values);
|
|
||||||
Q3 := Quartiles(2,0.75,ncases,values);
|
|
||||||
IQrange := Q3 - Q1;
|
|
||||||
lReport.Add('First Quartile: %10.3f', [Q1]);
|
|
||||||
lReport.Add('Median: %10.3f', [Q2]);
|
|
||||||
lReport.Add('Third Quartile: %10.3f', [Q3]);
|
|
||||||
lReport.Add('Interquartile range: %10.3f', [IQrange]);
|
|
||||||
lReport.Add('');
|
|
||||||
end;
|
|
||||||
|
|
||||||
if (AllQrtilesChk.Checked) then
|
|
||||||
begin
|
|
||||||
lReport.Add('Alternative Methods for Obtaining Quartiles');
|
|
||||||
lReport.Add(' Method 1 2 3 4 5 6 7 8');
|
|
||||||
lReport.Add('Pcntile');
|
|
||||||
Q1 := Quartiles(1,0.25,ncases,values);
|
|
||||||
Q12 := Quartiles(2,0.25,ncases,values);
|
|
||||||
Q13 := Quartiles(3,0.25,ncases,values);
|
|
||||||
Q14 := Quartiles(4,0.25,ncases,values);
|
|
||||||
Q15 := Quartiles(5,0.25,ncases,values);
|
|
||||||
Q16 := Quartiles(6,0.25,ncases,values);
|
|
||||||
Q17 := Quartiles(7,0.25,ncases,values);
|
|
||||||
Q18 := Quartiles(8,0.25,ncases,values);
|
|
||||||
lReport.Add('Q1 %8.3f%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f', [Q1,Q12,Q13,Q14,Q15,Q16,Q17,Q18]);
|
|
||||||
Q2 := Quartiles(1,0.5,ncases,values);
|
|
||||||
Q22 := Quartiles(2,0.5,ncases,values);
|
|
||||||
Q23 := Quartiles(3,0.5,ncases,values);
|
|
||||||
Q24 := Quartiles(4,0.5,ncases,values);
|
|
||||||
Q25 := Quartiles(5,0.5,ncases,values);
|
|
||||||
Q26 := Quartiles(6,0.5,ncases,values);
|
|
||||||
Q27 := Quartiles(7,0.5,ncases,values);
|
|
||||||
Q28 := Quartiles(8,0.5,ncases,values);
|
|
||||||
lReport.Add('Q2 %8.3f%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f', [Q2,Q22,Q23,Q24,Q25,Q26,Q27,Q28]);
|
|
||||||
Q3 := Quartiles(1,0.75,ncases,values);
|
|
||||||
Q32 := Quartiles(2,0.75,ncases,values);
|
|
||||||
Q33 := Quartiles(3,0.75,ncases,values);
|
|
||||||
Q34 := Quartiles(4,0.75,ncases,values);
|
|
||||||
Q35 := Quartiles(5,0.75,ncases,values);
|
|
||||||
Q36 := Quartiles(6,0.75,ncases,values);
|
|
||||||
Q37 := Quartiles(7,0.75,ncases,values);
|
|
||||||
Q38 := Quartiles(8,0.75,ncases,values);
|
|
||||||
lReport.Add('Q3 %8.3f%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f', [Q3,Q32,Q33,Q34,Q35,Q36,Q37,Q38]);
|
|
||||||
lReport.Add('');
|
|
||||||
lReport.Add('NOTES:');
|
|
||||||
lReport.Add('Method 1 is the weighted average at X[np] where ');
|
|
||||||
lReport.Add(' n is no. of cases, p is percentile / 100');
|
|
||||||
lReport.Add('Method 2 is the weighted average at X[(n+1)p] This is used in this program.');
|
|
||||||
lReport.Add('Method 3 is the empirical distribution function.');
|
|
||||||
lReport.Add('Method 4 is called the empirical distribution function - averaging.');
|
|
||||||
lReport.Add('Method 5 is called the empirical distribution function = Interpolation.');
|
|
||||||
lReport.Add('Method 6 is the closest observation method.');
|
|
||||||
lReport.Add('Method 7 is from the TrueBasic Statistics Graphics Toolkit.');
|
|
||||||
lReport.Add('Method 8 was used in an older Microsoft Excel version.');
|
|
||||||
lReport.Add('See the internet site http://www.xycoon.com/ for the above.');
|
|
||||||
lReport.Add('');
|
|
||||||
end; // end of experimental alternatives
|
|
||||||
lReport.Add(DIVIDER_SMALL_AUTO);
|
|
||||||
end; // next j variable
|
|
||||||
|
|
||||||
FReportFrame.DisplayReport(lReport);
|
|
||||||
|
|
||||||
finally
|
finally
|
||||||
|
// Clean up
|
||||||
|
lDescrStats.Free;
|
||||||
lReport.Free;
|
lReport.Free;
|
||||||
Selected := nil;
|
end;
|
||||||
Values := nil;
|
end;
|
||||||
pcntrank := nil;
|
|
||||||
|
|
||||||
|
function TDescriptiveFrm.GetReportFrame(APageIndex: Integer): TReportFrame;
|
||||||
|
var
|
||||||
|
page: TTabSheet;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
if (APageIndex >=0) and (APageIndex < PageControl.PageCount) then
|
||||||
|
begin
|
||||||
|
page := PageControl.Pages[APageIndex];
|
||||||
|
if (page.ControlCount > 0) and (page.Controls[0] is TReportFrame) then
|
||||||
|
Result := TReportFrame(page.Controls[0]);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -406,6 +648,12 @@ var
|
|||||||
i: integer;
|
i: integer;
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
|
|
||||||
|
for i := PageControl.PageCount-1 downto 1 do
|
||||||
|
PageControl.Pages[i].Free;
|
||||||
|
|
||||||
|
PageControl.Pages[0].Caption := 'Report';
|
||||||
|
|
||||||
CIEdit.Text := FormatFloat('0.0', DEFAULT_CONFIDENCE_LEVEL_PERCENT);
|
CIEdit.Text := FormatFloat('0.0', DEFAULT_CONFIDENCE_LEVEL_PERCENT);
|
||||||
VarList.Clear;
|
VarList.Clear;
|
||||||
SelList.Clear;
|
SelList.Clear;
|
||||||
@ -447,9 +695,16 @@ procedure TDescriptiveFrm.UpdateBtnStates;
|
|||||||
var
|
var
|
||||||
lSelected: Boolean;
|
lSelected: Boolean;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
F: TReportFrame;
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
|
|
||||||
|
for i := 0 to PageControl.PageCount-1 do
|
||||||
|
begin
|
||||||
|
F := GetReportFrame(i);
|
||||||
|
if Assigned(F) then F.Clear;
|
||||||
|
end;
|
||||||
|
|
||||||
lSelected := false;
|
lSelected := false;
|
||||||
for i := 0 to VarList.Items.Count-1 do
|
for i := 0 to VarList.Items.Count-1 do
|
||||||
if VarList.Selected[i] then
|
if VarList.Selected[i] then
|
||||||
@ -478,5 +733,43 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDescriptiveFrm.zScoresToGrid(AColIndex: Integer;
|
||||||
|
const AColsSelected: IntDyneVec; AMean, AStdDev: Double);
|
||||||
|
var
|
||||||
|
i, idx: Integer;
|
||||||
|
value, zValue: Double;
|
||||||
|
varName: String;
|
||||||
|
begin
|
||||||
|
if AStdDev = 0 then begin
|
||||||
|
ErrorMsg('Cannot store z values to grid because StdDev is zero.');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
varName := OS3MainFrm.DataGrid.Cells[AColIndex, 0] + '_z';
|
||||||
|
idx := OS3MainFrm.DataGrid.Rows[0].IndexOf(varName);
|
||||||
|
if idx = -1 then
|
||||||
|
begin
|
||||||
|
DictionaryFrm.NewVar(NoVariables + 1);
|
||||||
|
DictionaryFrm.DictGrid.Cells[1, NoVariables] := varName;
|
||||||
|
OS3MainFrm.DataGrid.Cells[NoVariables, 0] := varName;
|
||||||
|
idx := NoVariables;
|
||||||
|
end;
|
||||||
|
|
||||||
|
for i := 1 to NoCases do
|
||||||
|
begin
|
||||||
|
if CaseChk.Checked then
|
||||||
|
begin
|
||||||
|
if not ValidValue(i, AColsSelected[AColIndex]) then continue;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if not GoodRecord(i, Length(AColsSelected), AColsSelected) then continue;
|
||||||
|
|
||||||
|
value := StrToFloat(OS3MainFrm.DataGrid.Cells[AColIndex, i]);
|
||||||
|
zValue := (value - AMean) / AStdDev;
|
||||||
|
OS3MainFrm.DataGrid.Cells[idx, i] := Format('%8.5f', [zValue]);
|
||||||
|
// to do: read number of decimal places from Dictionary and use in Format().
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
inherited BasicStatsParamsForm: TBasicStatsParamsForm
|
inherited BasicStatsParamsForm: TBasicStatsParamsForm
|
||||||
|
Height = 459
|
||||||
Width = 709
|
Width = 709
|
||||||
Caption = 'BasicStatsParamsForm'
|
Caption = 'BasicStatsParamsForm'
|
||||||
|
ClientHeight = 459
|
||||||
ClientWidth = 709
|
ClientWidth = 709
|
||||||
Position = poMainFormCenter
|
Position = poMainFormCenter
|
||||||
object ParamsPanel: TPanel[0]
|
object ParamsPanel: TPanel[0]
|
||||||
|
@ -77,7 +77,7 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
|
|
||||||
w := MaxValue([HelpBtn.Width, ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]);
|
w := MaxValue([HelpBtn.Width, ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]);
|
||||||
HelpBtn.Constraints.MinWidth := 2;
|
HelpBtn.Constraints.MinWidth := w;
|
||||||
ResetBtn.Constraints.MinWidth := w;
|
ResetBtn.Constraints.MinWidth := w;
|
||||||
ComputeBtn.Constraints.MinWidth := w;
|
ComputeBtn.Constraints.MinWidth := w;
|
||||||
CloseBtn.Constraints.MinWidth := w;
|
CloseBtn.Constraints.MinWidth := w;
|
||||||
@ -89,6 +89,8 @@ begin
|
|||||||
|
|
||||||
Position := poDesigned;
|
Position := poDesigned;
|
||||||
FAutoSized := true;
|
FAutoSized := true;
|
||||||
|
|
||||||
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ function poly(const c: Array of double; nord: integer; x: double): double; // RE
|
|||||||
procedure swilk (var init : boolean; const x: DblDyneVec; n, n1, n2: integer;
|
procedure swilk (var init : boolean; const x: DblDyneVec; n, n1, n2: integer;
|
||||||
const a: DblDyneVec; var w, pw: double; out ifault: integer);
|
const a: DblDyneVec; var w, pw: double; out ifault: integer);
|
||||||
procedure SVDinverse(VAR a : DblDyneMat; N : integer);
|
procedure SVDinverse(VAR a : DblDyneMat; N : integer);
|
||||||
function inverset(Probt, DF : double) : double;
|
function InverseT(Prob, DF: double): double;
|
||||||
function inversechi(p : double; k : integer) : double;
|
function inversechi(p : double; k : integer) : double;
|
||||||
function STUDENT(q,v,r : real) : real;
|
function STUDENT(q,v,r : real) : real;
|
||||||
function realraise(base,power : double ): double;
|
function realraise(base,power : double ): double;
|
||||||
@ -43,10 +43,12 @@ function UniStats(N : integer; VAR X : DblDyneVec; VAR z : DblDyneVec;
|
|||||||
VAR SESkew : double; VAR SEkurtosis : double; VAR min : double;
|
VAR SESkew : double; VAR SEkurtosis : double; VAR min : double;
|
||||||
VAR max : double; VAR Range : double; VAR MissValue : string) :
|
VAR max : double; VAR Range : double; VAR MissValue : string) :
|
||||||
integer;
|
integer;
|
||||||
function WholeValue(value : double) : double;
|
|
||||||
function FractionValue(value : double) : double;
|
//function WholeValue(value : double) : double;
|
||||||
function Quartiles(TypeQ : integer; pcntile : double; N : integer;
|
//function FractionValue(value : double) : double;
|
||||||
VAR values : DblDyneVec) : double;
|
|
||||||
|
function Quartiles(TypeQ: integer; Percentile: double; N: integer;
|
||||||
|
const Values: DblDyneVec): double;
|
||||||
|
|
||||||
function KolmogorovProb(z: double): double;
|
function KolmogorovProb(z: double): double;
|
||||||
function KolmogorovTest(na: integer; const a: DblDyneVec; nb: integer;
|
function KolmogorovTest(na: integer; const a: DblDyneVec; nb: integer;
|
||||||
@ -944,15 +946,14 @@ begin
|
|||||||
Result := prob;
|
Result := prob;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function inverset(Probt, DF : double) : double;
|
{ Returns the t value corresponding to a two-tailed t test probability. }
|
||||||
|
function InverseT(Prob, DF: double): double;
|
||||||
var
|
var
|
||||||
z, W, tValue: double;
|
z, W: double;
|
||||||
begin
|
begin
|
||||||
// Returns the t value corresponding to a two-tailed t test probability.
|
z := InverseZ(Prob);
|
||||||
z := inversez(Probt);
|
|
||||||
W := z * ((8.0 * DF + 3.0) / (1.0 + 8.0 * DF));
|
W := z * ((8.0 * DF + 3.0) / (1.0 + 8.0 * DF));
|
||||||
tValue := sqrt(DF * (exp(W * W / DF) - 1.0));
|
Result := sqrt(DF * (exp(W * W / DF) - 1.0));
|
||||||
inverset := tValue;
|
|
||||||
end;
|
end;
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
@ -1644,11 +1645,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function Quartiles(TypeQ : integer; pcntile : double; N : integer;
|
function Quartiles(TypeQ: integer; Percentile: double; N: integer;
|
||||||
VAR values : DblDyneVec) : double;
|
const Values: DblDyneVec): double;
|
||||||
VAR
|
var
|
||||||
whole, fraction, Myresult, np, avalue, avalue1 : double;
|
whole, fraction, np, lValue, lValue1: double;
|
||||||
subscript : integer;
|
subscript: integer;
|
||||||
begin
|
begin
|
||||||
{ for i := 0 to N - 1 do // this is for debugging
|
{ for i := 0 to N - 1 do // this is for debugging
|
||||||
begin
|
begin
|
||||||
@ -1656,46 +1657,52 @@ begin
|
|||||||
OutPutFrm.RichEdit.Lines.Add(outline);
|
OutPutFrm.RichEdit.Lines.Add(outline);
|
||||||
end;
|
end;
|
||||||
OutPutFrm.ShowModal;
|
OutPutFrm.ShowModal;
|
||||||
OutPutFrm.RichEdit.Clear; }
|
OutPutFrm.RichEdit.Clear;
|
||||||
|
}
|
||||||
case TypeQ of
|
case TypeQ of
|
||||||
1 : np := pcntile * N;
|
1 : np := Percentile * N;
|
||||||
2 : np := pcntile * (N + 1);
|
2 : np := Percentile * (N + 1);
|
||||||
3 : np := pcntile * N;
|
3 : np := Percentile * N;
|
||||||
4 : np := pcntile * N;
|
4 : np := Percentile * N;
|
||||||
5 : np := pcntile * (N - 1);
|
5 : np := Percentile * (N - 1);
|
||||||
6 : np := pcntile * N + 0.5;
|
6 : np := Percentile * N + 0.5;
|
||||||
7 : np := pcntile * (N + 1);
|
7 : np := Percentile * (N + 1);
|
||||||
8 : np := pcntile * (N + 1);
|
8 : np := Percentile * (N + 1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
whole := WholeValue(np);
|
whole := WholeValue(np);
|
||||||
fraction := FractionValue(np);
|
fraction := FractionValue(np);
|
||||||
subscript := Trunc(whole) - 1;
|
subscript := Trunc(whole) - 1;
|
||||||
avalue := values[subscript];
|
lValue := Values[subscript];
|
||||||
avalue1 := values[subscript + 1];
|
lValue1 := Values[subscript + 1];
|
||||||
|
|
||||||
case TypeQ of
|
case TypeQ of
|
||||||
1 : Myresult := ((1.0 - fraction) * values[subscript]) +
|
1 : Result := ((1.0 - fraction) * values[subscript]) + fraction * values[subscript + 1];
|
||||||
fraction * values[subscript + 1];
|
2 : Result := ((1.0 - fraction) * lValue) + fraction * lValue1; // values[subscript + 1];
|
||||||
2 : Myresult := ((1.0 - fraction) * avalue) +
|
3 : if (fraction = 0.0) then
|
||||||
fraction * avalue1; // values[subscript + 1];
|
Result := values[subscript]
|
||||||
3 : if (fraction = 0.0) then Myresult := values[subscript]
|
else
|
||||||
else Myresult := values[subscript + 1];
|
Result := values[subscript + 1];
|
||||||
4 : if (fraction = 0.0) then Myresult := 0.5 * (values[subscript] + values[subscript + 1])
|
4 : if (fraction = 0.0) then
|
||||||
else Myresult := values[subscript + 1];
|
Result := 0.5 * (values[subscript] + values[subscript + 1])
|
||||||
5 : if (fraction = 0.0) then Myresult := values[subscript + 1]
|
else
|
||||||
else Myresult := values[subscript + 1] + fraction * (values[subscript + 2] -
|
Result := values[subscript + 1];
|
||||||
values[subscript + 1]);
|
5 : if (fraction = 0.0) then
|
||||||
6 : Myresult := values[subscript];
|
Result := values[subscript + 1]
|
||||||
7 : if (fraction = 0.0) then Myresult := values[subscript]
|
else
|
||||||
else Myresult := fraction * values[subscript] +
|
Result := Values[subscript + 1] + fraction * (Values[subscript + 2] - values[subscript + 1]);
|
||||||
(1.0 - fraction) * values[subscript + 1];
|
6 : Result := values[subscript];
|
||||||
|
7 : if (fraction = 0.0) then
|
||||||
|
Result := values[subscript]
|
||||||
|
else
|
||||||
|
Result := fraction * Values[subscript] + (1.0 - fraction) * Values[subscript + 1];
|
||||||
8 : begin
|
8 : begin
|
||||||
if (fraction = 0.0) then Myresult := values[subscript];
|
if (fraction = 0.0) then Result := values[subscript];
|
||||||
if (fraction = 0.5) then Myresult := 0.5 * (values[subscript] + values[subscript + 1]);
|
if (fraction = 0.5) then Result := 0.5 * (values[subscript] + values[subscript + 1]);
|
||||||
if (fraction < 0.5) then Myresult := values[subscript];
|
if (fraction < 0.5) then Result := values[subscript];
|
||||||
if (fraction > 0.5) then Myresult := values[subscript + 1];
|
if (fraction > 0.5) then Result := values[subscript + 1];
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Result := Myresult;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function KolmogorovProb(z : double) : double;
|
function KolmogorovProb(z : double) : double;
|
||||||
|
Reference in New Issue
Block a user