LazStats: Inherit KappaUnit from BasicStatsReportFormUnit.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8016 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2021-05-09 16:52:18 +00:00
parent c9983bc26e
commit 7daa8215e6
4 changed files with 893 additions and 1035 deletions

View File

@ -926,7 +926,7 @@
<Unit102> <Unit102>
<Filename Value="forms\analysis\nonparametric\kappaunit.pas"/> <Filename Value="forms\analysis\nonparametric\kappaunit.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<ComponentName Value="WeightedKappaFrm"/> <ComponentName Value="WeightedKappaForm"/>
<HasResources Value="True"/> <HasResources Value="True"/>
<ResourceBaseClass Value="Form"/> <ResourceBaseClass Value="Form"/>
<UnitName Value="KappaUnit"/> <UnitName Value="KappaUnit"/>

View File

@ -1,34 +1,54 @@
object WeightedKappaFrm: TWeightedKappaFrm inherited WeightedKappaForm: TWeightedKappaForm
Left = 448 Left = 448
Height = 560 Height = 559
Top = 184 Top = 184
Width = 539 Width = 1086
HelpType = htKeyword HelpType = htKeyword
HelpKeyword = 'html/KappaandWeightedKappa.htm' HelpKeyword = 'html/KappaandWeightedKappa.htm'
AutoSize = True
Caption = 'Kappa and Weighted Kappa' Caption = 'Kappa and Weighted Kappa'
ClientHeight = 560 ClientHeight = 559
ClientWidth = 539 ClientWidth = 1086
OnActivate = FormActivate
OnCreate = FormCreate OnCreate = FormCreate
OnShow = FormShow inherited ParamsPanel: TPanel
Position = poMainFormCenter Height = 543
LCLVersion = '2.1.0.0' Width = 488
object InputGroup: TRadioGroup AutoSize = True
AnchorSideLeft.Control = Owner ClientHeight = 543
AnchorSideTop.Control = Owner ClientWidth = 488
AnchorSideRight.Control = Owner inherited CloseBtn: TButton
Left = 433
Top = 518
end
inherited ComputeBtn: TButton
Left = 349
Top = 518
end
inherited ResetBtn: TButton
Left = 287
Top = 518
end
inherited HelpBtn: TButton
Tag = 128
Left = 228
Top = 518
end
inherited ButtonBevel: TBevel
Top = 502
Width = 488
end
object InputGroup: TRadioGroup[5]
AnchorSideLeft.Control = ParamsPanel
AnchorSideTop.Control = ParamsPanel
AnchorSideRight.Control = ParamsPanel
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 8 Left = 0
Height = 89 Height = 89
Top = 8 Top = 0
Width = 488 Width = 488
Align = alCustom Align = alCustom
Anchors = [akTop, akLeft, akRight]
AutoFill = True AutoFill = True
AutoSize = True AutoSize = True
BorderSpacing.Left = 8
BorderSpacing.Top = 8
BorderSpacing.Right = 8
Caption = 'Input Options:' Caption = 'Input Options:'
ChildSizing.LeftRightSpacing = 6 ChildSizing.LeftRightSpacing = 6
ChildSizing.TopBottomSpacing = 6 ChildSizing.TopBottomSpacing = 6
@ -46,261 +66,229 @@ object WeightedKappaFrm: TWeightedKappaFrm
'Use proportions in a variable for a given row variable value and column variable value.' 'Use proportions in a variable for a given row variable value and column variable value.'
) )
OnClick = InputGroupClick OnClick = InputGroupClick
TabOrder = 0 TabOrder = 4
end end
object Label1: TLabel object Label1: TLabel[6]
AnchorSideLeft.Control = Owner AnchorSideLeft.Control = ParamsPanel
AnchorSideTop.Control = InputGroup AnchorSideTop.Control = InputGroup
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
Left = 8 Left = 0
Height = 15 Height = 15
Top = 105 Top = 97
Width = 46 Width = 46
BorderSpacing.Left = 8
BorderSpacing.Top = 8 BorderSpacing.Top = 8
Caption = 'Variables' Caption = 'Variables'
ParentColor = False ParentColor = False
end end
object VarList: TListBox object VarList: TListBox[7]
AnchorSideLeft.Control = Owner AnchorSideLeft.Control = ParamsPanel
AnchorSideTop.Control = Label1 AnchorSideTop.Control = Label1
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = RowIn AnchorSideRight.Control = RowIn
AnchorSideBottom.Control = NCasesEdit AnchorSideBottom.Control = NCasesEdit
Left = 8 Left = 0
Height = 358 Height = 357
Top = 122 Top = 114
Width = 265 Width = 230
Anchors = [akTop, akLeft, akRight, akBottom] Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Left = 8
BorderSpacing.Top = 2 BorderSpacing.Top = 2
BorderSpacing.Right = 8 BorderSpacing.Right = 8
ItemHeight = 0 ItemHeight = 0
OnDblClick = VarListDblClick
OnSelectionChange = VarListSelectionChange OnSelectionChange = VarListSelectionChange
TabOrder = 1 TabOrder = 5
end end
object NCasesLbl: TLabel object RowIn: TBitBtn[8]
AnchorSideLeft.Control = VarList
AnchorSideTop.Control = NCasesEdit
AnchorSideTop.Side = asrCenter
AnchorSideRight.Control = NCasesEdit
Left = 8
Height = 15
Top = 492
Width = 122
BorderSpacing.Right = 8
Caption = 'Total Number of Cases:'
ParentColor = False
end
object NCasesEdit: TEdit
AnchorSideLeft.Control = NCasesLbl
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = Bevel1
Left = 138
Height = 23
Top = 488
Width = 54
Alignment = taRightJustify
Anchors = [akLeft, akBottom]
BorderSpacing.Top = 8
BorderSpacing.Bottom = 8
TabOrder = 2
Text = 'NCasesEdit'
end
object RowIn: TBitBtn
AnchorSideLeft.Control = OptionsGroup AnchorSideLeft.Control = OptionsGroup
AnchorSideTop.Control = VarList AnchorSideTop.Control = VarList
Left = 281 Left = 238
Height = 28 Height = 28
Top = 122 Top = 114
Width = 28 Width = 28
Images = MainDataModule.ImageList Images = MainDataModule.ImageList
ImageIndex = 1 ImageIndex = 1
OnClick = RowInClick OnClick = RowInClick
Spacing = 0 Spacing = 0
TabOrder = 3 TabOrder = 6
end end
object RowOut: TBitBtn object RowOut: TBitBtn[9]
AnchorSideLeft.Control = OptionsGroup AnchorSideLeft.Control = OptionsGroup
AnchorSideTop.Control = RowIn AnchorSideTop.Control = RowIn
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
Left = 281 Left = 238
Height = 28 Height = 28
Top = 154 Top = 146
Width = 28 Width = 28
BorderSpacing.Top = 4 BorderSpacing.Top = 4
Images = MainDataModule.ImageList Images = MainDataModule.ImageList
ImageIndex = 0 ImageIndex = 0
OnClick = RowOutClick OnClick = RowOutClick
Spacing = 0 Spacing = 0
TabOrder = 4 TabOrder = 7
end end
object ColIn: TBitBtn object ColIn: TBitBtn[10]
AnchorSideLeft.Control = OptionsGroup AnchorSideLeft.Control = OptionsGroup
AnchorSideTop.Control = RowOut AnchorSideTop.Control = RowOut
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
Left = 281 Left = 238
Height = 28 Height = 28
Top = 202 Top = 194
Width = 28 Width = 28
BorderSpacing.Top = 20 BorderSpacing.Top = 20
Images = MainDataModule.ImageList Images = MainDataModule.ImageList
ImageIndex = 1 ImageIndex = 1
OnClick = ColInClick OnClick = ColInClick
Spacing = 0 Spacing = 0
TabOrder = 6 TabOrder = 8
end end
object ColOut: TBitBtn object ColOut: TBitBtn[11]
AnchorSideLeft.Control = OptionsGroup AnchorSideLeft.Control = OptionsGroup
AnchorSideTop.Control = ColIn AnchorSideTop.Control = ColIn
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
Left = 281 Left = 238
Height = 28 Height = 28
Top = 234 Top = 226
Width = 28 Width = 28
BorderSpacing.Top = 4 BorderSpacing.Top = 4
Images = MainDataModule.ImageList Images = MainDataModule.ImageList
ImageIndex = 0 ImageIndex = 0
OnClick = ColOutClick OnClick = ColOutClick
Spacing = 0 Spacing = 0
TabOrder = 7 TabOrder = 9
end end
object DepIn: TBitBtn object DepIn: TBitBtn[12]
AnchorSideLeft.Control = OptionsGroup AnchorSideLeft.Control = OptionsGroup
AnchorSideTop.Control = ColOut AnchorSideTop.Control = ColOut
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
Left = 281 Left = 238
Height = 28 Height = 28
Top = 282 Top = 274
Width = 28 Width = 28
BorderSpacing.Top = 20 BorderSpacing.Top = 20
Images = MainDataModule.ImageList Images = MainDataModule.ImageList
ImageIndex = 1 ImageIndex = 1
OnClick = DepInClick OnClick = DepInClick
Spacing = 0 Spacing = 0
TabOrder = 9 TabOrder = 10
end end
object DepOut: TBitBtn object DepOut: TBitBtn[13]
AnchorSideLeft.Control = OptionsGroup AnchorSideLeft.Control = OptionsGroup
AnchorSideTop.Control = DepIn AnchorSideTop.Control = DepIn
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
Left = 281 Left = 238
Height = 28 Height = 28
Top = 314 Top = 306
Width = 28 Width = 28
BorderSpacing.Top = 4 BorderSpacing.Top = 4
Images = MainDataModule.ImageList Images = MainDataModule.ImageList
ImageIndex = 0 ImageIndex = 0
OnClick = DepOutClick OnClick = DepOutClick
Spacing = 0 Spacing = 0
TabOrder = 10 TabOrder = 11
end end
object Label2: TLabel object Label2: TLabel[14]
AnchorSideLeft.Control = RaterAEdit AnchorSideLeft.Control = RaterAEdit
AnchorSideBottom.Control = RaterAEdit AnchorSideBottom.Control = RaterAEdit
Left = 317 Left = 274
Height = 15 Height = 15
Top = 130 Top = 122
Width = 38 Width = 38
Anchors = [akLeft, akBottom] Anchors = [akLeft, akBottom]
BorderSpacing.Bottom = 2 BorderSpacing.Bottom = 2
Caption = 'Rater A' Caption = 'Rater A'
ParentColor = False ParentColor = False
end end
object Label3: TLabel object Label3: TLabel[15]
AnchorSideLeft.Control = RaterBEdit AnchorSideLeft.Control = RaterBEdit
AnchorSideBottom.Control = RaterBEdit AnchorSideBottom.Control = RaterBEdit
Left = 317 Left = 274
Height = 15 Height = 15
Top = 210 Top = 202
Width = 37 Width = 37
Anchors = [akLeft, akBottom] Anchors = [akLeft, akBottom]
BorderSpacing.Bottom = 2 BorderSpacing.Bottom = 2
Caption = 'Rater B' Caption = 'Rater B'
ParentColor = False ParentColor = False
end end
object DepLbl: TLabel object DepLbl: TLabel[16]
AnchorSideLeft.Control = DepEdit AnchorSideLeft.Control = DepEdit
AnchorSideBottom.Control = DepEdit AnchorSideBottom.Control = DepEdit
Left = 317 Left = 274
Height = 15 Height = 15
Top = 290 Top = 282
Width = 99 Width = 99
Anchors = [akLeft, akBottom] Anchors = [akLeft, akBottom]
BorderSpacing.Bottom = 2 BorderSpacing.Bottom = 2
Caption = 'Variable to Analyze' Caption = 'Variable to Analyze'
ParentColor = False ParentColor = False
end end
object RaterAEdit: TEdit object RaterAEdit: TEdit[17]
AnchorSideLeft.Control = RowIn AnchorSideLeft.Control = RowIn
AnchorSideLeft.Side = asrBottom AnchorSideLeft.Side = asrBottom
AnchorSideRight.Control = OptionsGroup AnchorSideRight.Control = ParamsPanel
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = RowOut AnchorSideBottom.Control = RowOut
AnchorSideBottom.Side = asrBottom AnchorSideBottom.Side = asrBottom
Left = 317 Left = 274
Height = 23 Height = 23
Top = 147 Top = 139
Width = 214 Width = 214
Anchors = [akLeft, akRight, akBottom] Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 8 BorderSpacing.Left = 8
BorderSpacing.Bottom = 12 BorderSpacing.Bottom = 12
ReadOnly = True ReadOnly = True
TabOrder = 5 TabOrder = 12
Text = 'RaterAEdit' Text = 'RaterAEdit'
end end
object RaterBEdit: TEdit object RaterBEdit: TEdit[18]
AnchorSideLeft.Control = ColIn AnchorSideLeft.Control = ColIn
AnchorSideLeft.Side = asrBottom AnchorSideLeft.Side = asrBottom
AnchorSideRight.Control = OptionsGroup AnchorSideRight.Control = ParamsPanel
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = ColOut AnchorSideBottom.Control = ColOut
AnchorSideBottom.Side = asrBottom AnchorSideBottom.Side = asrBottom
Left = 317 Left = 274
Height = 23 Height = 23
Top = 227 Top = 219
Width = 214 Width = 214
Anchors = [akLeft, akRight, akBottom] Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 8 BorderSpacing.Left = 8
BorderSpacing.Bottom = 12 BorderSpacing.Bottom = 12
ReadOnly = True ReadOnly = True
TabOrder = 8 TabOrder = 13
Text = 'RaterBEdit' Text = 'RaterBEdit'
end end
object DepEdit: TEdit object DepEdit: TEdit[19]
AnchorSideLeft.Control = DepOut AnchorSideLeft.Control = DepOut
AnchorSideLeft.Side = asrBottom AnchorSideLeft.Side = asrBottom
AnchorSideRight.Control = OptionsGroup AnchorSideRight.Control = ParamsPanel
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = DepOut AnchorSideBottom.Control = DepOut
AnchorSideBottom.Side = asrBottom AnchorSideBottom.Side = asrBottom
Left = 317 Left = 274
Height = 23 Height = 23
Top = 307 Top = 299
Width = 214 Width = 214
Anchors = [akLeft, akRight, akBottom] Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 8 BorderSpacing.Left = 8
BorderSpacing.Bottom = 12 BorderSpacing.Bottom = 12
ReadOnly = True ReadOnly = True
TabOrder = 11 TabOrder = 14
Text = 'DepEdit' Text = 'DepEdit'
end end
object OptionsGroup: TGroupBox object OptionsGroup: TGroupBox[20]
AnchorSideLeft.Control = RowIn AnchorSideLeft.Control = RowIn
AnchorSideTop.Control = DepOut AnchorSideTop.Control = DepOut
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner AnchorSideRight.Control = ParamsPanel
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 281 Left = 238
Height = 156 Height = 156
Top = 354 Top = 346
Width = 250 Width = 250
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
AutoSize = True AutoSize = True
BorderSpacing.Top = 12 BorderSpacing.Top = 12
BorderSpacing.Right = 8
Caption = 'Options:' Caption = 'Options:'
ChildSizing.LeftRightSpacing = 12 ChildSizing.LeftRightSpacing = 12
ChildSizing.TopBottomSpacing = 6 ChildSizing.TopBottomSpacing = 6
@ -309,7 +297,7 @@ object WeightedKappaFrm: TWeightedKappaFrm
ChildSizing.ControlsPerLine = 1 ChildSizing.ControlsPerLine = 1
ClientHeight = 136 ClientHeight = 136
ClientWidth = 246 ClientWidth = 246
TabOrder = 12 TabOrder = 15
object ObsChk: TCheckBox object ObsChk: TCheckBox
Left = 12 Left = 12
Height = 19 Height = 19
@ -359,84 +347,38 @@ object WeightedKappaFrm: TWeightedKappaFrm
TabOrder = 5 TabOrder = 5
end end
end end
object ResetBtn: TButton object NCasesLbl: TLabel[21]
AnchorSideTop.Control = CloseBtn AnchorSideLeft.Control = VarList
AnchorSideRight.Control = ComputeBtn AnchorSideTop.Control = NCasesEdit
AnchorSideBottom.Side = asrBottom AnchorSideTop.Side = asrCenter
Left = 330 AnchorSideRight.Control = NCasesEdit
Height = 25
Top = 527
Width = 54
Anchors = [akTop, akRight]
AutoSize = True
BorderSpacing.Left = 8
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
Caption = 'Reset'
OnClick = ResetBtnClick
TabOrder = 13
end
object ComputeBtn: TButton
AnchorSideTop.Control = CloseBtn
AnchorSideRight.Control = CloseBtn
AnchorSideBottom.Side = asrBottom
Left = 392
Height = 25
Top = 527
Width = 76
Anchors = [akTop, akRight]
AutoSize = True
BorderSpacing.Left = 8
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
Caption = 'Compute'
OnClick = ComputeBtnClick
TabOrder = 14
end
object CloseBtn: TButton
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 476
Height = 25
Top = 527
Width = 55
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 8
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
Caption = 'Close'
ModalResult = 11
TabOrder = 15
end
object HelpBtn: TButton
Tag = 128
AnchorSideTop.Control = CloseBtn
AnchorSideRight.Control = ResetBtn
AnchorSideBottom.Side = asrBottom
Left = 271
Height = 25
Top = 527
Width = 51
Anchors = [akTop, akRight]
AutoSize = True
BorderSpacing.Left = 8
BorderSpacing.Right = 8
BorderSpacing.Bottom = 8
Caption = 'Help'
OnClick = HelpBtnClick
TabOrder = 16
end
object Bevel1: TBevel
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = CloseBtn
Left = 0 Left = 0
Height = 8 Height = 15
Top = 519 Top = 483
Width = 541 Width = 122
Anchors = [akLeft, akRight, akBottom] BorderSpacing.Right = 8
Shape = bsTopLine Caption = 'Total Number of Cases:'
ParentColor = False
end
object NCasesEdit: TEdit[22]
AnchorSideLeft.Control = NCasesLbl
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = ButtonBevel
Left = 130
Height = 23
Top = 479
Width = 54
Alignment = taRightJustify
Anchors = [akLeft, akBottom]
BorderSpacing.Top = 8
TabOrder = 16
Text = 'NCasesEdit'
end
end
inherited ParamsSplitter: TSplitter
Left = 500
Height = 559
end end
end end

View File

@ -7,19 +7,13 @@ interface
uses uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls, Buttons, StdCtrls, ExtCtrls, Buttons,
MainUnit, Globals, OutputUnit, FunctionsLib, DictionaryUnit, DataProcs, MainUnit, FunctionsLib, DictionaryUnit, MatrixLib, BasicStatsReportFormUnit;
MatrixLib, ContextHelpUnit;
type type
{ TWeightedKappaFrm } { TWeightedKappaForm }
TWeightedKappaFrm = class(TForm) TWeightedKappaForm = class(TBasicStatsReportForm)
Bevel1: TBevel;
HelpBtn: TButton;
ResetBtn: TButton;
ComputeBtn: TButton;
CloseBtn: TButton;
ObsChk: TCheckBox; ObsChk: TCheckBox;
ExpChk: TCheckBox; ExpChk: TCheckBox;
PropChk: TCheckBox; PropChk: TCheckBox;
@ -46,177 +40,55 @@ type
InputGroup: TRadioGroup; InputGroup: TRadioGroup;
procedure ColInClick(Sender: TObject); procedure ColInClick(Sender: TObject);
procedure ColOutClick(Sender: TObject); procedure ColOutClick(Sender: TObject);
procedure ComputeBtnClick(Sender: TObject);
procedure DepInClick(Sender: TObject); procedure DepInClick(Sender: TObject);
procedure DepOutClick(Sender: TObject); procedure DepOutClick(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure FormCreate(Sender: TObject); procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure HelpBtnClick(Sender: TObject);
procedure InputGroupClick(Sender: TObject); procedure InputGroupClick(Sender: TObject);
procedure ResetBtnClick(Sender: TObject);
procedure RowInClick(Sender: TObject); procedure RowInClick(Sender: TObject);
procedure RowOutClick(Sender: TObject); procedure RowOutClick(Sender: TObject);
procedure VarListDblClick(Sender: TObject);
procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean); procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean);
private private
{ private declarations } { private declarations }
FAutoSized: Boolean; protected
procedure UpdateBtnStates; procedure AdjustConstraints; override;
procedure Compute; override;
procedure UpdateBtnStates; override;
function Validate(out AMsg: String; out AControl: TWinControl): Boolean; override;
public public
{ public declarations } { public declarations }
procedure Reset; override;
end; end;
var var
WeightedKappaFrm: TWeightedKappaFrm; WeightedKappaForm: TWeightedKappaForm;
implementation implementation
{$R *.lfm}
uses uses
Math; Math,
Globals, DataProcs, GridProcs, Utils;
{ TWeightedKappaFrm } { TWeightedKappaForm }
procedure TWeightedKappaFrm.ResetBtnClick(Sender: TObject); procedure TWeightedKappaForm.AdjustConstraints;
var
i: integer;
begin begin
RaterAEdit.Text := ''; inherited;
RaterBEdit.Text := '';
DepEdit.Text := ''; ParamsPanel.Constraints.MinHeight :=
NCasesEdit.Text := ''; OptionsGroup.Top + OptionsGroup.Height +
InputGroup.ItemIndex := 0; ButtonBevel.Height + CloseBtn.BorderSpacing.Top + CloseBtn.Height;
VarList.Clear;
for i := 1 to NoVariables do ParamsPanel.Constraints.MinWidth := MaxValueI([
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); InputGroup.Width,
UpdateBtnStates; OptionsGroup.Width + NCasesEdit.Left + NCasesEdit.Width + VarList.BorderSpacing.Right
]);
end; end;
procedure TWeightedKappaFrm.RowInClick(Sender: TObject); procedure TWeightedKappaForm.ColInClick(Sender: TObject);
var
index: integer;
begin
index := VarList.ItemIndex;
if (index > -1) and (RaterAEdit.Text = '') then
begin
RaterAEdit.Text := VarList.Items[index];
VarList.Items.Delete(index);
end;
UpdateBtnStates;
end;
procedure TWeightedKappaFrm.RowOutClick(Sender: TObject);
begin
if RaterAEdit.Text <> '' then
begin
VarList.Items.Add(RaterAEdit.Text);
RaterAEdit.Text := '';
end;
UpdateBtnStates;
end;
procedure TWeightedKappaFrm.FormActivate(Sender: TObject);
var
w: Integer;
begin
if FAutoSized then
exit;
// Autosizing is not working for whatever reason...
//AutoSize := false;
w := MaxValue([HelpBtn.Width, ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]);
HelpBtn.Constraints.MinWidth := w;
ResetBtn.Constraints.MinWidth := w;
ComputeBtn.Constraints.MinWidth := w;
CloseBtn.Constraints.MinWidth := w;
//VarList.Constraints.MinHeight := OptionsGroup.Top + OptionsGroup.Height - NCasesEdit.Height - VarList.BorderSpacing.Bottom;
Constraints.MinWidth := Width;
Constraints.MinHeight := OptionsGroup.Top + OptionsGroup.Height + CloseBtn.Height + 2*CloseBtn.BorderSpacing.Bottom;
FAutoSized := true;
end;
procedure TWeightedKappaFrm.FormCreate(Sender: TObject);
begin
Assert(OS3MainFrm <> nil);
if DictionaryFrm = nil then
Application.CreateForm(TDictionaryFrm, DictionaryFrm);
end;
procedure TWeightedKappaFrm.FormShow(Sender: TObject);
begin
ResetBtnClick(self);
end;
procedure TWeightedKappaFrm.HelpBtnClick(Sender: TObject);
begin
if ContextHelpForm = nil then
Application.CreateForm(TContextHelpForm, ContextHelpForm);
ContextHelpForm.HelpMessage((Sender as TButton).tag);
end;
procedure TWeightedKappaFrm.InputGroupClick(Sender: TObject);
begin
(*
case InputGroup.ItemIndex of
0: begin // have to count cases in each row and col. combination
NCasesEdit.Enabled := false;
NCasesLbl.Enabled := false;
DepEdit.Enabled := false;
end;
1: begin // frequencies available for each row and column combo
DepLbl.Enabled := true;
NCasesLbl.Enabled := false;
NCasesEdit.Enabled := false;
DepEdit.Enabled := true;
end;
2: begin // only proportions available - get N size
DepLbl.Enabled := true;
NCasesEdit.Enabled := true;
NCasesLbl.Enabled := true;
DepEdit.Visible := Enabled;
end;
end;
*)
UpdateBtnStates;
(*
if (index = 2) then // only proportions available - get N size
begin
DepLbl.Visible := true;
NCasesEdit.Visible := true;
NCasesEdit.SetFocus;
DepIn.Enabled := true;
DepOut.Enabled := false;
DepIn.Visible := true;
DepOut.Visible := true;
DepEdit.Visible := true;
NCasesLbl.Visible := true;
end;
if (index = 1) then // frequencies available for each row and column combo
begin
DepLbl.Visible := true;
NCasesEdit.Visible := false;
DepIn.Enabled := true;
DepOut.Enabled := false;
DepIn.Visible := true;
DepOut.Visible := true;
DepEdit.Visible := true;
NCasesLbl.Visible := false;
end;
if (index = 0) then // have to count cases in each row and col. combination
begin
NCasesEdit.Visible := false;
DepIn.Visible := false;
DepOut.Visible := false;
DepEdit.Visible := false;
DepLbl.Visible := false;
NCasesLbl.Visible := false;
end;
*)
end;
procedure TWeightedKappaFrm.ColInClick(Sender: TObject);
var var
index: integer; index: integer;
begin begin
@ -229,7 +101,7 @@ begin
UpdateBtnStates; UpdateBtnStates;
end; end;
procedure TWeightedKappaFrm.ColOutClick(Sender: TObject); procedure TWeightedKappaForm.ColOutClick(Sender: TObject);
begin begin
if RaterBEdit.Text <> '' then if RaterBEdit.Text <> '' then
begin begin
@ -239,141 +111,63 @@ begin
UpdateBtnStates; UpdateBtnStates;
end; end;
procedure TWeightedKappaFrm.ComputeBtnClick(Sender: TObject); procedure TWeightedKappaForm.Compute;
var var
ColNoSelected: IntDyneVec = nil;
Freq: IntDyneMat = nil;
Prop: DblDyneMat = nil;
Expected: DblDyneMat = nil;
CellChi: DblDyneMat = nil;
weights: DblDyneMat = nil;
quadweights: DblDyneMat = nil;
RowLabels: StrDyneVec = nil;
ColLabels: StrDyneVec = nil;
i, j, k, RowNo, ColNo, DepNo, MinRow, MaxRow, MinCol, MaxCol: integer; i, j, k, RowNo, ColNo, DepNo, MinRow, MaxRow, MinCol, MaxCol: integer;
Row, Col, NoSelected, Ncases, Nrows, Ncols, FObs, df : integer; Row, Col, Ncases, Nrows, Ncols, FObs, df: integer;
RowLabels, ColLabels : StrDyneVec;
ColNoSelected : IntDyneVec;
cellstring : string;
outline : string;
Freq : IntDyneMat;
Prop, Expected, CellChi : DblDyneMat;
PObs, ChiSquare, ProbChi, likelihood, Fval, phi: double; PObs, ChiSquare, ProbChi, likelihood, Fval, phi: double;
yates, aresult : boolean; yates: boolean;
title: string; title: string;
Adjchisqr, Adjprobchi, problikelihood, pearsonr: double; Adjchisqr, Adjprobchi, problikelihood, pearsonr: double;
pobserved, SumX, SumY, VarX, VarY, obsdiag, expdiag, expnondiag: double; pobserved, SumX, SumY, VarX, VarY, obsdiag, expdiag, expnondiag: double;
pexpected, MantelHaenszel, MHprob, CoefCont, CramerV, Kappa : double; pexpected, MantelHaenszel, MHprob, CoefCont, CramerV: Double;
KappaU, KappaL, KappaQ: double;
Frq: integer; Frq: integer;
weights, quadweights : DblDyneMat;
lReport: TStrings; lReport: TStrings;
begin begin
if RaterAEdit.Text = '' then
begin
MessageDlg('Rater A is not specified.', mtError, [mbOK], 0);
exit;
end;
if RaterBEdit.Text = '' then
begin
MessageDlg('Rater B is not specified.', mtError, [mbOK], 0);
exit;
end;
if InputGroup.ItemIndex > 0 then
begin
if DepEdit.Text = '' then
begin
MessageDlg('Dependent variable is not specified.', mtError, [mbOK], 0);
exit;
end;
end;
if InputGroup.ItemIndex = 2 then
begin
if NCasesEdit.Text = '' then
begin
NCasesEdit.SetFocus;
MessageDlg('Total number of cases is not specified.', mtError, [mbOK], 0);
exit;
end;
if not TryStrToInt(NCasesEdit.Text, i) then
begin
NCasesEdit.SetFocus;
MessageDlg('Total number of cases is not a valid number.', mtError, [mbOK], 0);
exit;
end;
end;
SetLength(ColNoSelected,NoVariables);
yates := false;
RowNo := 0;
ColNo := 0;
DepNo := 0;
pobserved := 0.0; pobserved := 0.0;
pexpected := 0.0; pexpected := 0.0;
for i := 1 to NoVariables do RowNo := GetVariableIndex(OS3MainFrm.DataGrid, RaterAEdit.Text);
begin ColNo := GetVariableIndex(OS3MainFrm.DataGrid, RaterBEdit.Text);
cellstring := OS3MainFrm.DataGrid.Cells[i,0]; DepNo := GetVariableIndex(OS3MainFrm.DataGrid, DepEdit.Text);
if (cellstring = RaterAEdit.Text) then RowNo := i;
if (cellstring = RaterBEdit.Text) then ColNo := i;
if (cellstring = DepEdit.Text) then DepNo := i;
end;
(*
if ((InputGroup.ItemIndex > 0) and (DepNo = 0)) then
begin
ShowMessage('ERROR! You must select a dependent variable.');
ColNoSelected := nil;
exit;
end;
if ((RowNo = 0) or (ColNo = 0)) then // || (DepNo == 0))
begin
ShowMessage('ERROR! A required variable has not been selected.');
ColNoSelected := nil;
exit;
end;
*)
aresult := ValidValue(RowNo,1); if (not DataProcs.ValidValue(RowNo, 1)) or (not DataProcs.ValidValue(ColNo, 1)) then
if not aresult then
begin
ColNoSelected := nil;
exit; exit;
end; if (InputGroup.ItemIndex = 1) and (not DataProcs.ValidValue(DepNo, 1)) then
aresult := ValidValue(ColNo,1); exit;
if not aresult then if (InputGroup.ItemIndex = 2) and (not DataProcs.ValidValue(DepNo, 0)) then
begin
ColNoSelected := nil;
exit; exit;
end;
ColNoSelected[0] := RowNo; if (InputGroup.ItemIndex = 0) then
ColNoSelected[1] := ColNo; SetLength(ColNoSelected, 2)
NoSelected := 2; else
if (InputGroup.ItemIndex > 0) then // for reading proportions or frequencies
begin begin
NoSelected := 3; // for reading proportions or frequencies
SetLength(ColNoSelected, 3);
ColNoSelected[2] := DepNo; ColNoSelected[2] := DepNo;
end; end;
if (InputGroup.ItemIndex = 1) then ColNoSelected[0] := RowNo;
begin ColNoSelected[1] := ColNo;
aresult := ValidValue(DepNo,1);
if (aresult = false) then
begin
ColNoSelected := nil;
exit;
end;
end;
if (InputGroup.ItemIndex = 2) then
begin
aresult := ValidValue(DepNo,0);
if (aresult = false) then
begin
ColNoSelected := nil;
exit;
end;
end;
// get min and max of row and col numbers // get min and max of row and col numbers
MinRow := 1000; MinRow := MaxInt;
MaxRow := 0; MaxRow := 0;
MinCol := 1000; MinCol := MaxInt;
MaxCol := 0; MaxCol := 0;
for i := 1 to NoCases do for i := 1 to NoCases do
begin begin
if (not GoodRecord(i,NoSelected,ColNoSelected)) then continue; if (not GoodRecord(OS3MainFrm.DataGrid, i,ColNoSelected)) then Continue;
Row := round(StrToFloat(OS3MainFrm.DataGrid.Cells[RowNo,i])); Row := round(StrToFloat(OS3MainFrm.DataGrid.Cells[RowNo,i]));
Col := round(StrToFloat(OS3MainFrm.DataGrid.Cells[ColNo,i])); Col := round(StrToFloat(OS3MainFrm.DataGrid.Cells[ColNo,i]));
if (Row > MaxRow) then MaxRow := Row; if (Row > MaxRow) then MaxRow := Row;
@ -402,11 +196,11 @@ begin
// get cell data // get cell data
Ncases := 0; Ncases := 0;
if (InputGroup.ItemIndex = 0) then case InputGroup.ItemIndex of
begin // count number of cases in each row and column combination 0: begin // count number of cases in each row and column combination
for i := 1 to NoCases do for i := 1 to NoCases do
begin begin
if (not GoodRecord(i,NoSelected,ColNoSelected)) then if (not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected)) then
continue; continue;
Ncases := Ncases + 1; Ncases := Ncases + 1;
Row := round(StrToFloat(OS3MainFrm.DataGrid.Cells[RowNo,i])); Row := round(StrToFloat(OS3MainFrm.DataGrid.Cells[RowNo,i]));
@ -416,11 +210,11 @@ begin
Freq[Row-1,Col-1] := Freq[Row-1,Col-1] + 1; Freq[Row-1,Col-1] := Freq[Row-1,Col-1] + 1;
end; end;
end; end;
if (InputGroup.ItemIndex = 1) then // read frequencies data from grid 1: begin // read frequencies data from grid
begin
for i := 1 to NoCases do for i := 1 to NoCases do
begin begin
if (not GoodRecord(i,NoSelected,ColNoSelected)) then continue; if (not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected)) then
continue;
Row := round(StrToFloat(OS3MainFrm.DataGrid.Cells[RowNo,i])); Row := round(StrToFloat(OS3MainFrm.DataGrid.Cells[RowNo,i]));
Col := round(StrToFloat(OS3MainFrm.DataGrid.Cells[ColNo,i])); Col := round(StrToFloat(OS3MainFrm.DataGrid.Cells[ColNo,i]));
Row := Row - MinRow + 1; Row := Row - MinRow + 1;
@ -430,12 +224,12 @@ begin
Ncases := Ncases + FObs; Ncases := Ncases + FObs;
end; end;
end; end;
if (InputGroup.ItemIndex = 2) then // get no. of cases and proportions for each cell 2: begin // get no. of cases and proportions for each cell
begin
Ncases := StrToInt(NCasesEdit.Text); Ncases := StrToInt(NCasesEdit.Text);
for i := 1 to NoCases do for i := 1 to NoCases do
begin begin
if (not GoodRecord(i,NoSelected,ColNoSelected)) then continue; if (not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected)) then
continue;
Row := round(StrToFloat(OS3MainFrm.DataGrid.Cells[RowNo,i])); Row := round(StrToFloat(OS3MainFrm.DataGrid.Cells[RowNo,i]));
Col := round(StrToFloat(OS3MainFrm.DataGrid.Cells[ColNo,i])); Col := round(StrToFloat(OS3MainFrm.DataGrid.Cells[ColNo,i]));
Row := Row - MinRow + 1; Row := Row - MinRow + 1;
@ -443,36 +237,31 @@ begin
PObs := round(StrToFloat(OS3MainFrm.DataGrid.Cells[DepNo,i])); PObs := round(StrToFloat(OS3MainFrm.DataGrid.Cells[DepNo,i]));
Frq := round(PObs * Ncases); Frq := round(PObs * Ncases);
Fval := PObs * Ncases; Fval := PObs * Ncases;
if (Fval - Frq < 0.5) then Frq := round(Fval) if (Fval - Frq < 0.5) then
else Frq := ceil(Fval); Frq := round(Fval)
else
Frq := ceil(Fval);
Freq[Row-1,Col-1] := Freq[Row-1,Col-1] + Frq; Freq[Row-1,Col-1] := Freq[Row-1,Col-1] + Frq;
end; end;
end; end;
end;
Freq[Nrows, Ncols] := Ncases; Freq[Nrows, Ncols] := Ncases;
// Now, calculate expected values // Now, calculate expected values
// Get row totals first // Get row totals first
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
Freq[i-1,Ncols] := Freq[i-1,Ncols] + Freq[i-1,j-1]; Freq[i-1,Ncols] := Freq[i-1,Ncols] + Freq[i-1,j-1];
end;
end;
// Get col totals next // Get col totals next
for j := 1 to Ncols do for j := 1 to Ncols do
begin
for i := 1 to Nrows do for i := 1 to Nrows do
begin
Freq[Nrows,j-1] := Freq[Nrows,j-1] + Freq[i-1,j-1]; Freq[Nrows,j-1] := Freq[Nrows,j-1] + Freq[i-1,j-1];
end;
end;
// Then get expected values and cell chi-squares // Then get expected values and cell chi-squares
yates := YatesChk.Checked and (Nrows = 2) and (Ncols = 2);
ChiSquare := 0.0; ChiSquare := 0.0;
Adjchisqr := 0.0; Adjchisqr := 0.0;
if ((YatesChk.Checked) and (Nrows = 2) and (Ncols = 2)) then yates := true;
for i := 1 to Nrows do for i := 1 to Nrows do
begin begin
for j := 1 to Ncols do for j := 1 to Ncols do
@ -482,14 +271,14 @@ begin
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 else
begin begin
MessageDlg('Zero expected value found.', mtError, [mbOK], 0); ErrorMsg('Zero expected value found.');
CellChi[i-1,j-1] := 0.0; CellChi[i-1,j-1] := 0.0;
end; end;
ChiSquare := ChiSquare + CellChi[i-1,j-1]; ChiSquare := ChiSquare + CellChi[i-1,j-1];
end; end;
end; end;
df := (Nrows - 1) * (Ncols - 1); 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 begin
Adjchisqr := abs((Freq[0,0] * Freq[1,1]) - (Freq[0,1] * Freq[1,0])); 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
@ -502,29 +291,29 @@ begin
lReport := TStringList.Create; lReport := TStringList.Create;
try try
lReport.Add('CHI-SQUARE ANALYSIS RESULTS FOR ' + RaterAEdit.Text + ' AND ' + RaterBEdit.Text); lReport.Add('CHI-SQUARE ANALYSIS RESULTS FOR ' + RaterAEdit.Text + ' AND ' + RaterBEdit.Text);
lReport.Add('No. of Cases = %d', [Ncases]); lReport.Add('No. of Cases: %d', [Ncases]);
lReport.Add(''); lReport.Add('');
// print tables requested by use // print tables requested by use
if (ObsChk.Checked) then if ObsChk.Checked then
begin begin
IntArrayPrint(Freq, Nrows+1, Ncols+1, 'Frequencies', IntArrayPrint(Freq, Nrows+1, Ncols+1, 'Frequencies',
RowLabels, ColLabels, 'OBSERVED FREQUENCIES', lReport); RowLabels, ColLabels, 'OBSERVED FREQUENCIES', lReport);
lReport.Add('------------------------------------------------------------------------------'); lReport.Add(DIVIDER_SMALL_AUTO);
lReport.Add(''); lReport.Add('');
end; end;
if (ExpChk.Checked) then if ExpChk.Checked then
begin begin
outline := 'EXPECTED FREQUENCIES'; // Expected frequencies
MatPrint(Expected, Nrows, Ncols, outline, RowLabels, ColLabels, NoCases, lReport); MatPrint(Expected, Nrows, Ncols, 'EXPECTED FREQUENCIES', RowLabels, ColLabels, NoCases, lReport);
lReport.Add('------------------------------------------------------------------------------'); lReport.Add(DIVIDER_SMALL_AUTO);
lReport.Add(''); lReport.Add('');
end; end;
if (PropChk.Checked) then if PropChk.Checked then
begin begin
outline := 'ROW PROPORTIONS'; // Row proportions
for i := 1 to Nrows + 1 do for i := 1 to Nrows + 1 do
begin begin
for j := 1 to Ncols do for j := 1 to Ncols do
@ -537,13 +326,13 @@ begin
if (Freq[i-1, Ncols] > 0.0) then if (Freq[i-1, Ncols] > 0.0) then
Prop[i-1, Ncols] := 1.0 Prop[i-1, Ncols] := 1.0
else else
Prop[i-1][Ncols] := 0.0; Prop[i-1, Ncols] := 0.0;
end; end;
MatPrint(Prop, Nrows+1, Ncols+1, outline, RowLabels, ColLabels, NoCases, lReport); MatPrint(Prop, Nrows+1, Ncols+1, 'ROW PROPORTIONS', RowLabels, ColLabels, NoCases, lReport);
lReport.Add('------------------------------------------------------------------------------'); lReport.Add(DIVIDER_SMALL_AUTO);
lReport.Add(''); lReport.Add('');
outline := 'COLUMN PROPORTIONS'; // Column proportions
for j := 1 to Ncols + 1 do for j := 1 to Ncols + 1 do
begin begin
for i := 1 to Nrows do for i := 1 to Nrows do
@ -554,34 +343,32 @@ begin
Prop[i-1, j-1] := 0.0; Prop[i-1, j-1] := 0.0;
end; end;
if (Freq[Nrows, j-1] > 0.0) then if (Freq[Nrows, j-1] > 0.0) then
Prop[Nrows][j-1] := 1.0 Prop[Nrows, j-1] := 1.0
else else
Prop[Nrows, j-1] := 0.0; Prop[Nrows, j-1] := 0.0;
end; end;
MatPrint(Prop, Nrows+1, Ncols+1, outline, RowLabels, ColLabels, NoCases, lReport); MatPrint(Prop, Nrows+1, Ncols+1, 'COLUMN PROPORTIONS', RowLabels, ColLabels, NoCases, lReport);
lReport.Add('------------------------------------------------------------------------------'); lReport.Add(DIVIDER_SMALL_AUTO);
lReport.Add(''); lReport.Add('');
outline := 'PROPORTIONS OF TOTAL N'; // Proportions of total n
for i := 1 to Nrows + 1 do for i := 1 to Nrows + 1 do
for j := 1 to Ncols + 1 do Prop[i-1,j-1] := Freq[i-1,j-1] / Ncases; for j := 1 to Ncols + 1 do Prop[i-1,j-1] := Freq[i-1,j-1] / Ncases;
Prop[Nrows,Ncols] := 1.0; Prop[Nrows,Ncols] := 1.0;
MatPrint(Prop, Nrows+1, Ncols+1, outline, RowLabels, ColLabels, NoCases, lReport); MatPrint(Prop, Nrows+1, Ncols+1, 'PROPORTIONS OF TOTAL N', RowLabels, ColLabels, NoCases, lReport);
lReport.Add('------------------------------------------------------------------------------'); lReport.Add(DIVIDER_SMALL_AUTO);
lReport.Add(''); lReport.Add('');
end; end;
if (ChiChk.Checked) then if ChiChk.Checked then
begin begin
outline := 'CHI-SQUARED VALUE FOR CELLS'; // Chi-squared value for cells
MatPrint(CellChi, Nrows, Ncols, outline, RowLabels, ColLabels, NoCases, lReport); MatPrint(CellChi, Nrows, Ncols, 'CHI-SQUARED VALUE FOR CELLS', RowLabels, ColLabels, NoCases, lReport);
lReport.Add('------------------------------------------------------------------------------'); lReport.Add(DIVIDER_SMALL_AUTO);
lReport.Add(''); lReport.Add('');
end; end;
lReport.Add('');
lReport.Add('Chi-square: %.3f with D.F. %d. Prob. > value %.3f', [ChiSquare, df, ProbChi]); lReport.Add('Chi-square: %.3f with D.F. %d. Prob. > value %.3f', [ChiSquare, df, ProbChi]);
lReport.Add('');
if yates then if yates then
lReport.Add('Chi-square using Yates correction %.3f and Prob > value %.3f', [Adjchisqr, Adjprobchi]); lReport.Add('Chi-square using Yates correction %.3f and Prob > value %.3f', [Adjchisqr, Adjprobchi]);
@ -593,11 +380,9 @@ begin
likelihood := -2.0 * likelihood; likelihood := -2.0 * likelihood;
problikelihood := 1.0 - chisquaredprob(likelihood,df); problikelihood := 1.0 - chisquaredprob(likelihood,df);
lReport.Add('Likelihood Ratio %.3f with prob. > value %.4f', [likelihood, problikelihood]); lReport.Add('Likelihood Ratio %.3f with prob. > value %.4f', [likelihood, problikelihood]);
lReport.Add('');
phi := sqrt(ChiSquare / Ncases); phi := sqrt(ChiSquare / Ncases);
lReport.Add('phi correlation: %.4f', [phi]); lReport.Add('phi correlation: %.4f', [phi]);
lReport.Add('');
pearsonr := 0.0; pearsonr := 0.0;
SumX := 0.0; SumX := 0.0;
@ -615,17 +400,14 @@ begin
pearsonr := pearsonr + ((i+1)*(j+1) * Freq[i,j]); pearsonr := pearsonr + ((i+1)*(j+1) * Freq[i,j]);
pearsonr := pearsonr - (SumX * SumY / Ncases); pearsonr := pearsonr - (SumX * SumY / Ncases);
pearsonr := pearsonr / sqrt(VarX * VarY); pearsonr := pearsonr / sqrt(VarX * VarY);
lReport.Add('Pearson Correlation r = %6.4f', [pearsonr]); lReport.Add('Pearson Correlation r: %.4f', [pearsonr]);
lReport.Add('');
MantelHaenszel := (Ncases-1) * (pearsonr * pearsonr); MantelHaenszel := (Ncases-1) * (pearsonr * pearsonr);
MHprob := 1.0 - chisquaredprob(MantelHaenszel,1); MHprob := 1.0 - chisquaredprob(MantelHaenszel,1);
lReport.Add('Mantel-Haenszel Test of Linear Association: %.3f with probability > value = %.4f', [MantelHaenszel, MHprob]); lReport.Add('Mantel-Haenszel Test of Linear Association: %.3f with probability > value = %.4f', [MantelHaenszel, MHprob]);
lReport.Add('');
CoefCont := sqrt(ChiSquare / (ChiSquare + Ncases)); CoefCont := sqrt(ChiSquare / (ChiSquare + Ncases));
lReport.Add('The coefficient of contingency: %.3f', [CoefCont]); lReport.Add('Coefficient of contingency: %.3f', [CoefCont]);
lReport.Add('');
if (Nrows < Ncols) then if (Nrows < Ncols) then
CramerV := sqrt(ChiSquare / (Ncases * ((Nrows-1)))) CramerV := sqrt(ChiSquare / (Ncases * ((Nrows-1))))
@ -636,6 +418,10 @@ begin
// kappa // kappa
if (Nrows = Ncols) then if (Nrows = Ncols) then
begin begin
lReport.Add('');
lReport.Add(DIVIDER_AUTO);
lReport.Add('');
obsdiag := 0.0; obsdiag := 0.0;
expdiag := 0.0; expdiag := 0.0;
for i := 0 to Nrows - 1 do for i := 0 to Nrows - 1 do
@ -644,9 +430,8 @@ begin
expdiag := expdiag + Expected[i,i]; expdiag := expdiag + Expected[i,i];
end; end;
expnondiag := Ncases - expdiag; expnondiag := Ncases - expdiag;
Kappa := (obsdiag - expdiag) / expnondiag; // Unweighted kappa
lReport.Add(''); KappaU := (obsdiag - expdiag) / expnondiag;
lReport.Add('Unweighted Kappa: %.4f', [Kappa]);
// get linear weights // get linear weights
SetLength(weights,Nrows,Ncols); SetLength(weights,Nrows,Ncols);
@ -668,14 +453,14 @@ begin
end; end;
end; end;
outline := 'Observed Linear Weights'; // Observed Linear Weights
MatPrint(weights, Nrows, Ncols, outline, RowLabels, ColLabels, NoCases, lReport); MatPrint(weights, Nrows, Ncols, 'Observed Linear Weights', RowLabels, ColLabels, NoCases, lReport);
lReport.Add('------------------------------------------------------------------------------'); lReport.Add(DIVIDER_SMALL_AUTO);
lReport.Add(''); lReport.Add('');
outline := 'Observed Quadratic Weights'; // Observed Quadratic Weights
MatPrint(quadweights, Nrows, Ncols, outline, RowLabels, ColLabels, NoCases, lReport); MatPrint(quadweights, Nrows, Ncols, 'Observed Quadratic Weights', RowLabels, ColLabels, NoCases, lReport);
lReport.Add('------------------------------------------------------------------------------'); lReport.Add(DIVIDER_SMALL_AUTO);
lReport.Add(''); lReport.Add('');
for i := 0 to Nrows - 1 do for i := 0 to Nrows - 1 do
@ -686,8 +471,8 @@ begin
pexpected := pexpected + (Expected[i,j] / Ncases) * weights[i,j]; pexpected := pexpected + (Expected[i,j] / Ncases) * weights[i,j];
end; end;
end; end;
Kappa := (pobserved - pexpected) / (1.0 - pexpected); // Linear weighted kappa
lReport.Add('Linear Weighted Kappa: %.4f', [Kappa]); KappaL := (pobserved - pexpected) / (1.0 - pexpected);
pobserved := 0.0; pobserved := 0.0;
pexpected := 0.0; pexpected := 0.0;
@ -699,19 +484,21 @@ begin
pexpected := pexpected + (Expected[i,j] / Ncases) * quadweights[i,j]; pexpected := pexpected + (Expected[i,j] / Ncases) * quadweights[i,j];
end; end;
end; end;
Kappa := (pobserved - pexpected) / (1.0 - pexpected); // Quadratic weighted kappa
lReport.Add('Quadratic Weighted Kappa: %.4f', [Kappa]); KappaQ := (pobserved - pexpected) / (1.0 - pexpected);
quadweights := nil;
weights := nil; lReport.Add('Unweighted Kappa: %.4f', [KappaU]);
lReport.Add('Linear Weighted Kappa: %.4f', [KappaL]);
lReport.Add('Quadratic Weighted Kappa: %.4f', [KappaQ]);
end; end;
DisplayReport(lReport); FReportFrame.DisplayReport(lReport);
finally finally
lReport.Free; lReport.Free;
end; end;
// save frequency data file if elected // save frequency data file if elected
if ((SaveChk.Checked) and (InputGroup.ItemIndex = 0)) then if (SaveChk.Checked and (InputGroup.ItemIndex = 0)) then
begin begin
ClearGrid; ClearGrid;
for i := 1 to 3 do DictionaryFrm.NewVar(i); for i := 1 to 3 do DictionaryFrm.NewVar(i);
@ -734,11 +521,8 @@ begin
end; end;
end; end;
for i := 1 to k - 1 do for i := 1 to k - 1 do
begin OS3MainFrm.DataGrid.Cells[0,i] := 'CASE ' + IntToStr(i);
title := 'CASE ' + IntToStr(i); title := InputBox('FILE:', 'File Name:', 'Frequencies.laz');
OS3MainFrm.DataGrid.Cells[0,i] := title;
end;
title := InputBox('FILE:','File Name:','Frequencies.LAZ');
OS3MainFrm.FileNameEdit.Text := title; OS3MainFrm.FileNameEdit.Text := title;
OS3MainFrm.NoVarsEdit.Text := IntToStr(3); OS3MainFrm.NoVarsEdit.Text := IntToStr(3);
OS3MainFrm.NoCasesEdit.Text := IntToStr(k-1); OS3MainFrm.NoCasesEdit.Text := IntToStr(k-1);
@ -758,7 +542,8 @@ begin
ColNoSelected := nil; ColNoSelected := nil;
end; end;
procedure TWeightedKappaFrm.DepInClick(Sender: TObject);
procedure TWeightedKappaForm.DepInClick(Sender: TObject);
var var
index: integer; index: integer;
begin begin
@ -771,7 +556,8 @@ begin
UpdateBtnStates; UpdateBtnStates;
end; end;
procedure TWeightedKappaFrm.DepOutClick(Sender: TObject);
procedure TWeightedKappaForm.DepOutClick(Sender: TObject);
begin begin
if DepEdit.Text <> '' then if DepEdit.Text <> '' then
begin begin
@ -781,7 +567,59 @@ begin
UpdateBtnStates; UpdateBtnStates;
end; end;
procedure TWeightedKappaFrm.UpdateBtnStates;
procedure TWeightedKappaForm.FormCreate(Sender: TObject);
begin
if DictionaryFrm = nil then
Application.CreateForm(TDictionaryFrm, DictionaryFrm);
end;
procedure TWeightedKappaForm.InputGroupClick(Sender: TObject);
begin
UpdateBtnStates;
end;
procedure TWeightedKappaForm.Reset;
begin
RaterAEdit.Text := '';
RaterBEdit.Text := '';
DepEdit.Text := '';
NCasesEdit.Text := '';
CollectVariableNames(OS3MainFrm.DataGrid, VarList.Items);
UpdateBtnStates;
end;
procedure TWeightedKappaForm.RowInClick(Sender: TObject);
var
index: integer;
begin
index := VarList.ItemIndex;
if (index > -1) and (RaterAEdit.Text = '') then
begin
RaterAEdit.Text := VarList.Items[index];
VarList.Items.Delete(index);
end;
UpdateBtnStates;
end;
procedure TWeightedKappaForm.RowOutClick(Sender: TObject);
begin
if RaterAEdit.Text <> '' then
begin
VarList.Items.Add(RaterAEdit.Text);
RaterAEdit.Text := '';
end;
UpdateBtnStates;
end;
procedure TWeightedKappaForm.UpdateBtnStates;
begin begin
RowIn.Enabled := (VarList.ItemIndex > -1) and (RaterAEdit.Text = ''); RowIn.Enabled := (VarList.ItemIndex > -1) and (RaterAEdit.Text = '');
RowOut.Enabled := (RaterAEdit.Text <> ''); RowOut.Enabled := (RaterAEdit.Text <> '');
@ -798,13 +636,91 @@ begin
NCasesLbl.Enabled := NCasesEdit.Enabled; NCasesLbl.Enabled := NCasesEdit.Enabled;
end; end;
procedure TWeightedKappaFrm.VarListSelectionChange(Sender: TObject; User: boolean);
function TWeightedKappaForm.Validate(out AMsg: String; out AControl: TWinControl): Boolean;
var
n: Integer;
begin
Result := false;
if InputGroup.ItemIndex = -1 then
begin
AMsg := 'No input option selected.';
AControl := InputGroup;
exit;
end;
if RaterAEdit.Text = '' then
begin
AMsg := 'Rater A is not specified.';
AControl := RaterAEdit;
exit;
end;
if RaterBEdit.Text = '' then
begin
AMsg := 'Rater B is not specified.';
AControl := RaterBEdit;
exit;
end;
if InputGroup.ItemIndex > 0 then
begin
if DepEdit.Text = '' then
begin
AMsg := 'Dependent variable is not specified.';
AControl := DepEdit;
exit;
end;
end;
if InputGroup.ItemIndex = 2 then
begin
if NCasesEdit.Text = '' then
begin
AMsg := 'Total number of cases is not specified.';
AControl := NCasesEdit;
exit;
end;
if not TryStrToInt(NCasesEdit.Text, n) then
begin
AMsg := 'Total number of cases is not a valid number.';
AControl := NCasesEdit;
exit;
end;
end;
Result := true;
end;
procedure TWeightedKappaForm.VarListDblClick(Sender: TObject);
var
index: Integer;
begin
index := VarList.ItemIndex;
if index > -1 then begin
if RaterAEdit.Text = '' then
RaterAEdit.Text := VarList.Items[index]
else
if RaterBEdit.Text = '' then
RaterBEdit.Text := VarList.Items[index]
else
if DepEdit.Enabled and (DepEdit.Text = '') then
DepEdit.Text := VarList.Items[index]
else
exit;
VarList.Items.Delete(index);
UpdateBtnStates;
end;
end;
procedure TWeightedKappaForm.VarListSelectionChange(Sender: TObject; User: boolean);
begin begin
UpdateBtnStates; UpdateBtnStates;
end; end;
initialization
{$I kappaunit.lrs}
end. end.

View File

@ -1777,9 +1777,9 @@ end;
// Menu "Analysis" > "Nonparametric" > "Kappa and Weighted Kappa" // Menu "Analysis" > "Nonparametric" > "Kappa and Weighted Kappa"
procedure TOS3MainFrm.mnuAnalysisNonPar_WeightedKappaClick(Sender: TObject); procedure TOS3MainFrm.mnuAnalysisNonPar_WeightedKappaClick(Sender: TObject);
begin begin
if WeightedKappaFrm = nil then if WeightedKappaForm = nil then
Application.CreateForm(TWeightedKappaFrm, WeightedKappaFrm); Application.CreateForm(TWeightedKappaForm, WeightedKappaForm);
WeightedKappaFrm.ShowModal; WeightedKappaForm.ShowModal;
end; end;
// Menu "Analysis" > "Nonparametric" > "Life table" // Menu "Analysis" > "Nonparametric" > "Life table"