From bd9d5086b8d326c35093693fe4ad2724749ffe4e Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Sun, 25 Oct 2020 21:41:09 +0000 Subject: [PATCH] LazStats: Add pagecontrol tabs to ChiSqrUnits for partial reports. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7804 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../analysis/nonparametric/chisqrunit.lfm | 28 +- .../analysis/nonparametric/chisqrunit.pas | 734 ++++++++++-------- .../forms/misc/basicstatsreportformunit.pas | 1 + .../source/frames/reportframeunit.pas | 2 +- 4 files changed, 445 insertions(+), 320 deletions(-) diff --git a/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.lfm b/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.lfm index 00d0f3346..3c8127f4b 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.lfm +++ b/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.lfm @@ -61,7 +61,7 @@ inherited ChiSqrFrm: TChiSqrFrm ClientHeight = 69 ClientWidth = 420 Items.Strings = ( - 'Count vases classified by row and column vectors in the data grid' + 'Count cases classified by row and column vectors in the data grid' 'Use frequencies recorded in the data grid for row and column variables' 'Use proportions recorded in the data grid for row and column variables' ) @@ -391,4 +391,30 @@ inherited ChiSqrFrm: TChiSqrFrm Left = 436 Height = 503 end + object PageControl: TPageControl[2] + Left = 445 + Height = 487 + Top = 8 + Width = 561 + ActivePage = ResultsPage + Align = alClient + BorderSpacing.Left = 4 + BorderSpacing.Top = 8 + BorderSpacing.Right = 8 + BorderSpacing.Bottom = 8 + TabIndex = 0 + TabOrder = 2 + object ResultsPage: TTabSheet + Caption = 'Results' + end + object FrequenciesPage: TTabSheet + Caption = 'Frequencies' + end + object RowColPage: TTabSheet + Caption = 'Row/Column Proportions' + end + object CellChiSqrPage: TTabSheet + Caption = 'Cell ChiSqr' + end + end end diff --git a/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.pas b/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.pas index bed11b03a..5a051c754 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.pas +++ b/applications/lazstats/source/forms/analysis/nonparametric/chisqrunit.pas @@ -6,9 +6,9 @@ interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, - ExtCtrls, StdCtrls, Buttons, + ExtCtrls, StdCtrls, Buttons, ComCtrls, MainUnit, FunctionsLib, GraphLib, Globals, MatrixLib, DataProcs, - DictionaryUnit, BasicStatsReportFormUnit; + DictionaryUnit, ReportFrameUnit, BasicStatsReportFormUnit; type @@ -17,10 +17,15 @@ type TChiSqrFrm = class(TBasicStatsReportForm) ObsChk: TCheckBox; ExpChk: TCheckBox; + PageControl: TPageControl; PropsChk: TCheckBox; CellChiChk: TCheckBox; SaveFChk: TCheckBox; OptionsGroup: TGroupBox; + ResultsPage: TTabSheet; + FrequenciesPage: TTabSheet; + RowColPage: TTabSheet; + CellChiSqrPage: TTabSheet; YatesChk: TCheckBox; RowIn: TBitBtn; RowOut: TBitBtn; @@ -48,8 +53,12 @@ type procedure RowOutClick(Sender: TObject); procedure VarListDblClick(Sender: TObject); procedure VarListSelectionChange(Sender: TObject; User: boolean); + private - + FFrequenciesReportFrame: TReportFrame; + FRowColPropsReportFrame: TReportFrame; + FCellChiSqrReportFrame: TReportFrame; + protected procedure AdjustConstraints; override; procedure Compute; override; @@ -69,7 +78,8 @@ implementation {$R *.lfm} uses - Math; + Math, + Utils, GridProcs; { TChiSqrFrm } @@ -78,8 +88,48 @@ begin inherited; if DictionaryFrm = nil then Application.CreateForm(TDictionaryFrm, DictionaryFrm); + + FReportFrame.Parent := ResultsPage; + FReportFrame.BorderSpacing.Left := 0; + FReportFrame.BorderSpacing.Top := 0; + FReportFrame.BorderSpacing.Bottom := 0; + FReportFrame.BorderSpacing.Right := 0; + InitToolbar(FReportFrame.ReportToolbar, tpRight); + + FFrequenciesReportFrame := TReportFrame.Create(self); + FFrequenciesReportFrame.Name := ''; + FFrequenciesReportFrame.Parent := FrequenciesPage; + FFrequenciesReportFrame.Align := alClient; + FFrequenciesReportFrame.BorderSpacing.Left := 0; + FFrequenciesReportFrame.BorderSpacing.Top := 0; + FFrequenciesReportFrame.BorderSpacing.Bottom := 0; + FFrequenciesReportFrame.BorderSpacing.Right := 0; + InitToolbar(FFrequenciesReportFrame.ReportToolbar, tpRight); + + FRowColPropsReportFrame := TReportFrame.Create(self); + FRowColPropsReportFrame.Name := ''; + FRowColPropsReportFrame.Parent := RowColPage; + FRowColPropsReportFrame.Align := alClient; + FRowColPropsReportFrame.BorderSpacing.Left := 0; + FRowColPropsReportFrame.BorderSpacing.Top := 0; + FRowColPropsReportFrame.BorderSpacing.Bottom := 0; + FRowColPropsReportFrame.BorderSpacing.Right := 0; + InitToolbar(FRowColPropsReportFrame.ReportToolbar, tpRight); + + FCellChiSqrReportFrame := TReportFrame.Create(self); + FCellChiSqrReportFrame.Name := ''; + FCellChiSqrReportFrame.Parent := CellChiSqrPage; + FCellChiSqrReportFrame.Align := alClient; + FCellChiSqrReportFrame.BorderSpacing.Left := 0; + FCellChiSqrReportFrame.BorderSpacing.Top := 0; + FCellChiSqrReportFrame.BorderSpacing.Bottom := 0; + FCellChiSqrReportFrame.BorderSpacing.Right := 0; + InitToolbar(FCellChiSqrReportFrame.ReportToolbar, tpRight); + + PageControl.ActivePageIndex := 0; end; + procedure TChiSqrFrm.AdjustConstraints; begin inherited; @@ -127,347 +177,391 @@ var Prop: DblDyneMat = nil; Expected: DblDyneMat = nil; CellChi: DblDyneMat = nil; + RowLabels: StrDyneVec = nil; + ColLabels: StrDyneVec = nil; + yates : boolean = false; - i, j, RowNo, ColNo, DepNo, MinRow, MaxRow, MinCol, MaxCol : integer; - Row, Col, NoSelected, Ncases, Nrows, Ncols, FObs, df : integer; - RowLabels, ColLabels : StrDyneVec; - cellstring: string; - PObs, ChiSquare, ProbChi, phi, SumX, SumY, VarX, VarY, liklihood : double; - yates : boolean; + NoSelected, NCases, NRows, NCols: Integer; + i, j, RowNo, ColNo, DepNo, MinRow, MaxRow, MinCol, MaxCol: integer; + Row, Col, FObs, df: integer; + PObs, ChiSquare, ProbChi, phi, SumX, SumY, VarX, VarY, likelihood: double; title : string; - Adjchisqr, probliklihood, G, pearsonr, MantelHaenszel, MHprob : double; - Adjprobchi, CoefCont, CramerV : double; + AdjChiSqr, AdjProbChi, probLikelihood, G, pearsonr, MantelHaenszel, MHprob: double; + CoefCont, CramerV: double; lReport: TStrings; begin - SetLength(ColNoSelected, NoVariables); - yates := false; - RowNo := 0; - ColNo := 0; - DepNo := 0; - for i := 1 to NoVariables do - begin - cellstring := OS3MainFrm.DataGrid.Cells[i,0]; - if cellstring = RowEdit.Text then RowNo := i; - if cellstring = ColEdit.Text then ColNo := i; - if cellstring = DepEdit.Text then DepNo := i; - end; - ColNoSelected[0] := RowNo; - ColNoSelected[1] := ColNo; - NoSelected := 2; - if InputGrp.ItemIndex > 0 then // for reading proportions or frequencies - begin - NoSelected := 3; - ColNoSelected[2] := DepNo; - end; - // get min and max of row and col numbers - MinRow := 1000; - MaxRow := 0; - MinCol := 1000; - MaxCol := 0; - for i := 1 to NoCases do - begin - if not GoodRecord(i,NoSelected,ColNoSelected) then continue; - Row := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[RowNo,i]))); - Col := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNo,i]))); - if Row > MaxRow then MaxRow := Row; - if Row < MinRow then MinRow := Row; - if Col > MaxCol then MaxCol := Col; - if Col < MinCol then MinCol := Col; - end; - Nrows := MaxRow - MinRow + 1; - Ncols := MaxCol - MinCol + 1; + RowNo := GetVariableIndex(OS3MainFrm.DataGrid, RowEdit.Text); + ColNo := GetVariableIndex(OS3MainFrm.DataGrid, ColEdit.Text); + DepNo := GetVariableIndex(OS3MainFrm.DataGrid, DepEdit.Text); - // allocate and initialize - SetLength(Freq,Nrows+1,Ncols+1); - SetLength(Prop,Nrows+1,Ncols+1); - SetLength(Expected,Nrows,Ncols); - SetLength(CellChi,Nrows,Ncols); - SetLength(RowLabels,Nrows+1); - SetLength(ColLabels,Ncols+1); - for i := 1 to Nrows + 1 do - for j := 1 to Ncols + 1 do Freq[i-1,j-1] := 0; + SetLength(ColNoSelected, NoVariables); + ColNoSelected[0] := RowNo; + ColNoSelected[1] := ColNo; + NoSelected := 2; + if InputGrp.ItemIndex > 0 then // for reading proportions or frequencies + begin + NoSelected := 3; + ColNoSelected[2] := DepNo; + end; + SetLength(ColNoSelected, NoSelected); - // get cell data - NCases := 0; - case InputGrp.ItemIndex of - 0 : begin // count number of cases in each row and column combination - for i := 1 to NoCases do - begin - if not GoodRecord(i,NoSelected,ColNoSelected) then continue; - NCases := NCases + 1; - Row := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[RowNo,i]))); - Col := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNo,i]))); - Row := Row - MinRow + 1; - Col := Col - MinCol + 1; - Freq[Row-1,Col-1] := Freq[Row-1,Col-1] + 1; - end; - end; - 1 : begin // read frequencies data from grid - for i := 1 to NoCases do - begin - if not GoodRecord(i,NoSelected,ColNoSelected) then continue; - Row := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[RowNo,i]))); - Col := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNo,i]))); - Row := Row - MinRow + 1; - Col := Col - MinCol + 1; - FObs := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[DepNo,i]))); - Freq[Row-1,Col-1] := Freq[Row-1,Col-1] + FObs; - NCases := NCases + FObs; - end; - end; - 2 : begin // get no. of cases and proportions for each cell - NCases := StrToInt(NCasesEdit.Text); - for i := 1 to NoCases do - begin - if not GoodRecord(i,NoSelected,ColNoSelected) then continue; - Row := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[RowNo,i]))); - Col := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNo,i]))); - Row := Row - MinRow + 1; - Col := Col - MinCol + 1; - PObs := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[DepNo,i])); - Freq[Row-1,Col-1] := Freq[Row-1,Col-1] + round(PObs * NCases); - end; - end; - end; // end case - Freq[Nrows,Ncols] := NCases; + // Get min and max of row and col numbers + MinRow := MaxInt; + MaxRow := -MinRow; + MinCol := MaxInt; + MaxCol := -MinCol; + for i := 1 to NoCases do + begin + if not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected) then continue; + Row := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[RowNo, i]))); + Col := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNo, i]))); + if Row > MaxRow then MaxRow := Row; + if Row < MinRow then MinRow := Row; + if Col > MaxCol then MaxCol := Col; + if Col < MinCol then MinCol := Col; + end; + NRows := MaxRow - MinRow + 1; + NCols := MaxCol - MinCol + 1; - // Now, calculate expected values - // Get row totals first - for i := 1 to Nrows do - for j := 1 to Ncols do - Freq[i-1,Ncols] := Freq[i-1,Ncols] + Freq[i-1,j-1]; - // Get col totals next - for j := 1 to Ncols do - for i := 1 to Nrows do - Freq[Nrows,j-1] := Freq[Nrows,j-1] + Freq[i-1,j-1]; - // Then get expected values and cell chi-squares - ChiSquare := 0.0; - AdjChisqr := 0.0; - if (YatesChk.Checked) and (Nrows = 2) and (Ncols = 2) then yates := true; - for i := 1 to Nrows do - begin - for j := 1 to Ncols do + // allocate and initialize + SetLength(Freq, NRows+1, NCols+1); + SetLength(Prop, NRows+1, NCols+1); + SetLength(Expected, NRows, NCols); + SetLength(CellChi, NRows, NCols); + SetLength(RowLabels, NRows+1); + SetLength(ColLabels, NCols+1); + + for i := 1 to NRows + 1 do + for j := 1 to NCols + 1 do Freq[i-1, j-1] := 0; + + // get cell data + NCases := 0; + case InputGrp.ItemIndex of + 0 : begin // count number of cases in each row and column combination + for i := 1 to NoCases do begin - Expected[i-1,j-1] := Freq[Nrows,j-1] * Freq[i-1,Ncols] / NCases; - if Expected[i-1,j-1] > 0.0 then - CellChi[i-1,j-1] := sqr(Freq[i-1,j-1] - Expected[i-1,j-1]) / Expected[i-1,j-1] - else begin - MessageDlg('Zero expected value found.', mtError, [mbOK], 0); - CellChi[i-1,j-1] := 0.0; - end; - ChiSquare := ChiSquare + CellChi[i-1,j-1]; + if not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected) then continue; + NCases := NCases + 1; + Row := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[RowNo, i]))); + Col := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNo, i]))); + Row := Row - MinRow + 1; + Col := Col - MinCol + 1; + Freq[Row-1, Col-1] := Freq[Row-1, Col-1] + 1; end; + end; + 1 : begin // read frequencies data from grid + for i := 1 to NoCases do + begin + if not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected) then continue; + Row := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[RowNo, i]))); + Col := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNo, i]))); + Row := Row - MinRow + 1; + Col := Col - MinCol + 1; + FObs := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[DepNo, i]))); + Freq[Row-1, Col-1] := Freq[Row-1, Col-1] + FObs; + NCases := NCases + FObs; + end; + end; + 2 : begin // get no. of cases and proportions for each cell + NCases := StrToInt(NCasesEdit.Text); + for i := 1 to NoCases do + begin + if not GoodRecord(OS3MainFrm.Datagrid, i, ColNoSelected) then continue; + Row := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[RowNo, i]))); + Col := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ColNo, i]))); + Row := Row - MinRow + 1; + Col := Col - MinCol + 1; + PObs := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[DepNo, i])); + Freq[Row-1, Col-1] := Freq[Row-1, Col-1] + round(PObs * NCases); + end; end; - df := (Nrows - 1) * (Ncols - 1); - if yates = true then // 2 x 2 corrected chi-square - begin - Adjchisqr := abs((Freq[0,0] * Freq[1,1]) - (Freq[0,1] * Freq[1,0])); - Adjchisqr := sqr(Adjchisqr - NCases / 2.0) * NCases; // numerator - Adjchisqr := Adjchisqr / (Freq[0,2] * Freq[1,2] * Freq[2,0] * Freq[2,1]); - Adjprobchi := 1.0 - chisquaredprob(Adjchisqr,df); - end; - ProbChi := 1.0 - chisquaredprob(ChiSquare,df); // prob. larger chi + end; // end case + Freq[Nrows, Ncols] := NCases; + + // Calculate expected values + // Get row totals first + for i := 1 to NRows do + for j := 1 to Ncols do + Freq[i-1, NCols] := Freq[i-1, NCols] + Freq[i-1, j-1]; + + // Get col totals next + for j := 1 to NCols do + for i := 1 to NRows do + Freq[NRows, j-1] := Freq[NRows, j-1] + Freq[i-1, j-1]; + + // Then get expected values and cell chi-squares + ChiSquare := 0.0; + AdjChisqr := 0.0; + + if (YatesChk.Checked) and (NRows = 2) and (NCols = 2) then + yates := true; + + for i := 1 to NRows do + begin + for j := 1 to Ncols do + begin + Expected[i-1, j-1] := Freq[NRows, j-1] * Freq[i-1, NCols] / NCases; + if Expected[i-1, j-1] > 0.0 then + CellChi[i-1, j-1] := sqr(Freq[i-1, j-1] - Expected[i-1, j-1]) / Expected[i-1, j-1] + else begin + ErrorMsg('Zero expected value found.'); + CellChi[i-1,j-1] := 0.0; + end; + ChiSquare := ChiSquare + CellChi[i-1, j-1]; + end; + end; + df := (Nrows - 1) * (Ncols - 1); + if yates then // 2 x 2 corrected chi-square + begin + AdjChiSqr := abs((Freq[0,0] * Freq[1,1]) - (Freq[0,1] * Freq[1,0])); + AdjChiSqr := sqr(AdjChiSqr - NCases / 2.0) * NCases; // numerator + AdjChiSqr := AdjChiSqr / (Freq[0,2] * Freq[1,2] * Freq[2,0] * Freq[2,1]); + AdjProbChi := 1.0 - ChiSquaredProb(AdjChiSqr, df); + end; + ProbChi := 1.0 - ChiSquaredProb(ChiSquare, df); // prob. larger chi + + for i := 1 to NRows do RowLabels[i-1] := Format('Row %d', [i]); + RowLabels[NRows] := 'Total'; + + for j := 1 to NCols do ColLabels[j-1] := Format('Col.%d', [j]); + ColLabels[NCols] := 'Total'; + + // Print results to output frames + lReport := TStringList.Create; + try + // print frequencies tables requested by user + if ObsChk.Checked or ExpChk.Checked then + begin + FrequenciesPage.TabVisible := true; - //Print results to output form - lReport := TStringList.Create; - try lReport.Add('CHI-SQUARE ANALYSIS RESULTS'); - // print tables requested by use - for i := 1 to Nrows do RowLabels[i-1] := Format('Row %d', [i]); - RowLabels[Nrows] := 'Total'; - for j := 1 to Ncols do ColLabels[j-1] := Format('COL.%d', [j]); - ColLabels[Ncols] := 'Total'; - if ObsChk.Checked then begin - IntArrayPrint(Freq, Nrows+1, Ncols+1,'Rows', - RowLabels, ColLabels,'OBSERVED FREQUENCIES', lReport); - lReport.Add('------------------------------------------------------------------------------'); + IntArrayPrint(Freq, NRows+1, NCols+1, 'Rows', RowLabels, ColLabels, 'OBSERVED FREQUENCIES', lReport); + lReport.Add(DIVIDER_SMALL_AUTO); lReport.Add(''); end; if ExpChk.Checked then begin title := 'EXPECTED FREQUENCIES'; - MatPrint(Expected,Nrows,Ncols,title,RowLabels,ColLabels,NCases, lReport); - lReport.Add('------------------------------------------------------------------------------'); - lReport.Add(''); + MatPrint(Expected, NRows, NCols, title, RowLabels, ColLabels, NCases, lReport); end; + FFrequenciesReportFrame.DisplayReport(lReport); + lReport.Clear; + end else + FrequenciesPage.TabVisible := false; - if PropsChk.Checked then - begin - title := 'ROW PROPORTIONS'; - for i := 1 to Nrows + 1 do - begin - for j := 1 to Ncols do - begin - if Freq[i-1,Ncols] > 0.0 then - Prop[i-1,j-1] := Freq[i-1,j-1] / Freq[i-1,Ncols] - else Prop[i-1,j-1] := 0.0; - end; - if Freq[i-1,Ncols] > 0.0 then Prop[i-1,Ncols] := 1.0 - else Prop[i-1,Ncols] := 0.0; - end; - MatPrint(Prop,Nrows+1,Ncols+1,title,RowLabels,ColLabels,NCases, lReport); - lReport.Add('------------------------------------------------------------------------------'); - lReport.Add(''); - title := 'COLUMN PROPORTIONS'; - for j := 1 to Ncols + 1 do - begin - for i := 1 to Nrows do - begin - if Freq[Nrows,j-1] > 0.0 then - Prop[i-1,j-1] := Freq[i-1,j-1] / Freq[Nrows,j-1] - else Prop[i-1,j-1] := 0.0; - end; - if Freq[Nrows,j-1] > 0.0 then Prop[NRows,j-1] := 1.0 - else Prop[NRows,j-1] := 0.0; - end; - MatPrint(Prop,Nrows+1,Ncols+1,title,RowLabels,ColLabels,NCases, lReport); - lReport.Add('------------------------------------------------------------------------------'); - lReport.Add(''); - Title := 'PROPORTIONS OF TOTAL N'; - 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; - Prop[Nrows,Ncols] := 1.0; - MatPrint(Prop,Nrows+1,Ncols+1,title,RowLabels,ColLabels,NCases, lReport); - lReport.Add('------------------------------------------------------------------------------'); - lReport.Add(''); - end; - - if CellChiChk.Checked then - begin - title := 'CHI-SQUARED VALUE FOR CELLS'; - MatPrint(CellChi,Nrows,Ncols,title,RowLabels,ColLabels,NCases, lReport); - lReport.Add('------------------------------------------------------------------------------'); - lReport.Add(''); - end; - - lReport.Add('Chi-square: %.3f with D.F. = %d. Prob. > value %.3f', [ChiSquare, df, ProbChi]); - lReport.Add(''); - if yates then - lReport.Add('Chi-square using Yates correction: %.3f and Prob > value: %.3f', [Adjchisqr, Adjprobchi]); - - liklihood := 0.0; - for i := 0 to Nrows-1 do - for j := 0 to Ncols-1 do - if (Freq[i,j] > 0.0) then - liklihood := Liklihood + (Freq[i,j] * (ln(Expected[i,j] / Freq[i,j]))); - liklihood := -2.0 * liklihood; - probliklihood := 1.0 - chisquaredprob(liklihood,df); - lReport.Add('Likelihood Ratio: %.3f with prob. > value %.4f', [liklihood, probliklihood]); - - G := 0.0; - for i := 0 to Nrows-1 do - for j := 0 to Ncols-1 do - if (Expected[i,j] > 0) then - G := G + Freq[i,j] * (ln(Freq[i,j] / Expected[i,j])); - G := 2.0 * G; - probliklihood := 1.0 - chisquaredprob(G,df); - lReport.Add('G statistic: %.3f with prob. > value %.4f', [G, probliklihood]); - - if ((Nrows > 1) and (Ncols > 1)) then - begin - phi := sqrt(ChiSquare / Ncases); - lReport.Add('phi correlation: %.4f', [phi]); - lReport.Add(''); - - pearsonr := 0.0; - SumX := 0.0; - SumY := 0.0; - VarX := 0.0; - VarY := 0.0; - for i := 0 to Nrows-1 do SumX := SumX + ( (i+1) * Freq[i,Ncols] ); - for j := 0 to Ncols-1 do SumY := SumY + ( (j+1) * Freq[Nrows,j] ); - for i := 0 to Nrows-1 do VarX := VarX + ( ((i+1)*(i+1)) * Freq[i,Ncols] ); - for j := 0 to Ncols-1 do VarY := VarY + ( ((j+1)*(j+1)) * Freq[Nrows,j] ); - VarX := VarX - ((SumX * SumX) / Ncases); - VarY := VarY - ((SumY * SumY) / Ncases); - for i := 0 to Nrows-1 do - for j := 0 to Ncols-1 do - pearsonr := pearsonr + ((i+1)*(j+1) * Freq[i,j]); - pearsonr := pearsonr - (SumX * SumY / Ncases); - pearsonr := pearsonr / sqrt(VarX * VarY); - lReport.Add('Pearson Correlation r: %.4f', [pearsonr]); - lReport.Add(''); - - MantelHaenszel := (Ncases-1) * (pearsonr * pearsonr); - MHprob := 1.0 - chisquaredprob(MantelHaenszel,1); - lReport.Add('Mantel-Haenszel Test of Linear Association: %.3f with probability > value %.4f', [MantelHaenszel, MHprob]); - lReport.Add(''); - - CoefCont := sqrt(ChiSquare / (ChiSquare + Ncases)); - lReport.Add('The coefficient of contingency: %.3f', [CoefCont]); - lReport.Add(''); - - if (Nrows < Ncols) then - CramerV := sqrt(ChiSquare / (Ncases * ((Nrows-1)))) - else - CramerV := sqrt(ChiSquare / (Ncases * ((Ncols-1)))); - lReport.Add('Cramers V: %.3f', [CramerV]); - lReport.Add(''); - end; - - FReportFrame.DisplayReport(lReport); - finally - lReport.Free; - end; - - // save frequency data file if elected - if SaveFChk.Checked then + if PropsChk.Checked then begin - OS3MainFrm.mnuFileCloseClick(self); - OS3MainFrm.FileNameEdit.Text := ''; - for i := 1 to DictionaryFrm.DictGrid.RowCount - 1 do - for j := 0 to 7 do DictionaryFrm.DictGrid.Cells[j,i] := ''; - DictionaryFrm.DictGrid.RowCount := 1; -// DictionaryFrm.FileNameEdit.Text := ''; + RowColPage.TabVisible := true; + title := 'ROW PROPORTIONS'; + for i := 1 to NRows + 1 do + begin + for j := 1 to NCols do + begin + if Freq[i-1, NCols] > 0.0 then + Prop[i-1, j-1] := Freq[i-1, j-1] / Freq[i-1, NCols] + else + Prop[i-1, j-1] := 0.0; + end; + if Freq[i-1, NCols] > 0.0 then + Prop[i-1, NCols] := 1.0 + else + Prop[i-1, NCols] := 0.0; + end; + lReport.Add('CHI-SQUARE ANALYSIS RESULTS'); + lReport.Add(''); + MatPrint(Prop, NRows+1, NCols+1, title, RowLabels, ColLabels, NCases, lReport); - // get labels for new file - ColLabels[0] := 'ROW'; - ColLabels[1] := 'COL'; - ColLabels[2] := 'FREQ'; - // create new variables - Row := 0; - OS3MainFrm.DataGrid.ColCount := 4; - DictionaryFrm.DictGrid.ColCount := 8; - NoVariables := 0; - for i := 1 to 3 do - begin - col := NoVariables + 1; - DictionaryFrm.NewVar(col); - DictionaryFrm.DictGrid.Cells[1,col] := ColLabels[i-1]; - OS3MainFrm.DataGrid.Cells[col,0] := ColLabels[i-1]; - NoVariables := NoVariables + 1; - end; - OS3MainFrm.DataGrid.RowCount := (Nrows * NCols) + 1; - for i := 1 to Nrows do - begin - for j := 1 to Ncols do - begin - Row := Row + 1; - OS3MainFrm.DataGrid.Cells[0,Row] := Format('Case:%d',[Row]); - OS3MainFrm.DataGrid.Cells[1,Row] := IntToStr(i); - OS3MainFrm.DataGrid.Cells[2,Row] := IntToStr(j); - OS3MainFrm.DataGrid.Cells[3,Row] := IntToStr(Freq[i-1,j-1]); - end; - end; - NoCases := Row; - OS3MainFrm.FileNameEdit.Text := 'ChiSqrFreq.LAZ'; - OS3MainFrm.NoCasesEdit.Text := IntToStr(NoCases); - OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables); -// OS3MainFrm.SaveFileBtnClick(self); + lReport.Add(DIVIDER_SMALL_AUTO); + lReport.Add(''); + + title := 'COLUMN PROPORTIONS'; + for j := 1 to Ncols + 1 do + begin + for i := 1 to Nrows do + begin + if Freq[Nrows,j-1] > 0.0 then + Prop[i-1,j-1] := Freq[i-1,j-1] / Freq[Nrows,j-1] + else + Prop[i-1,j-1] := 0.0; + end; + if Freq[Nrows,j-1] > 0.0 then + Prop[NRows,j-1] := 1.0 + else + Prop[NRows,j-1] := 0.0; + end; + MatPrint(Prop, NRows+1, NCols+1, title, RowLabels, ColLabels, NCases, lReport); + + lReport.Add(DIVIDER_SMALL_AUTO); + lReport.Add(''); + + Title := 'PROPORTIONS OF TOTAL N'; + 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; + Prop[Nrows, Ncols] := 1.0; + MatPrint(Prop, NRows+1, NCols+1, title, RowLabels, ColLabels, NCases, lReport); + + lReport.Add(DIVIDER_SMALL_AUTO); + lReport.Add(''); + + FRowColPropsReportFrame.DisplayReport(lReport); + lReport.Clear; + end else + RowColPage.TabVisible := false; + + if CellChiChk.Checked then + begin + CellChiSqrPage.TabVisible := true; + lReport.Add('CHI-SQUARE ANALYSIS RESULTS'); + lReport.Add(''); + title := 'CHI-SQUARED VALUE FOR CELLS'; + MatPrint(CellChi, NRows, NCols, title, RowLabels, ColLabels, NCases, lReport); + FCellChiSqrReportFrame.DisplayReport(lReport); + lReport.Clear; + end else + CellChiSqrPage.TabVisible := false; + + lReport.Add('CHI-SQUARE ANALYSIS RESULTS'); + lReport.Add(''); + lReport.Add('Chi-square: %.3f', [ChiSquare]); + lReport.Add(' with %d degrees of freedom', [DF]); + lReport.Add(' Probability > value is %.4f', [ProbChi]); + lReport.Add(''); + if yates then + begin + lReport.Add('Chi-square using Yates correction: %.3f', [AdjChiSqr]); + lReport.Add(' Probability > value is %.4f', [AdjProbChi]); + lReport.Add(''); end; - //clean up - ColLabels := nil; - RowLabels := nil; - CellChi := nil; - Expected := nil; - Prop := nil; - Freq := nil; - ColNoSelected := nil; + likelihood := 0.0; + for i := 0 to NRows-1 do + for j := 0 to NCols-1 do + if (Freq[i, j] > 0.0) then + likelihood := Likelihood + (Freq[i, j] * (ln(Expected[i, j] / Freq[i,j ]))); + likelihood := -2.0 * likelihood; + probLikelihood := 1.0 - ChiSquaredProb(likelihood, df); + lReport.Add('Likelihood Ratio: %.3f', [likelihood]); + lReport.Add(' Probability > value is %.4f', [probLikelihood]); + lReport.Add(''); + + G := 0.0; + for i := 0 to NRows-1 do + for j := 0 to NCols-1 do + if (Expected[i, j] > 0) then + G := G + Freq[i, j] * (ln(Freq[i, j] / Expected[i, j])); + G := 2.0 * G; + probLikelihood := 1.0 - ChiSquaredProb(G, df); + lReport.Add('G statistic: %.3f ', [G]); + lReport.Add(' Probability > value is %.4f', [G, probLikelihood]); + lReport.Add(''); + + if ((NRows > 1) and (NCols > 1)) then + begin + phi := sqrt(ChiSquare / NCases); + lReport.Add('phi correlation: %.4f', [phi]); + lReport.Add(''); + + pearsonr := 0.0; + SumX := 0.0; + SumY := 0.0; + VarX := 0.0; + VarY := 0.0; + for i := 0 to NRows-1 do SumX := SumX + ( (i+1) * Freq[i, NCols] ); + for j := 0 to NCols-1 do SumY := SumY + ( (j+1) * Freq[NRows, j] ); + for i := 0 to NRows-1 do VarX := VarX + ( sqr(i+1) * Freq[i, NCols] ); + for j := 0 to NCols-1 do VarY := VarY + ( sqr(j+1) * Freq[NRows, j] ); + VarX := VarX - sqr(SumX) / NCases; + VarY := VarY - sqr(SumY) / NCases; + for i := 0 to NRows-1 do + for j := 0 to NCols-1 do + pearsonR := pearsonR + ((i+1)*(j+1) * Freq[i, j]); + pearsonR := pearsonR - (SumX * SumY / Ncases); + pearsonR := pearsonR / sqrt(VarX * VarY); + lReport.Add('Pearson Correlation r: %.4f', [pearsonR]); + lReport.Add(''); + + MantelHaenszel := (NCases-1) * sqr(pearsonR); + MHprob := 1.0 - ChiSquaredProb(MantelHaenszel, 1); + lReport.Add('Mantel-Haenszel Test of Linear Association: %.3f', [MantelHaenszel]); + lReport.Add(' Probability > value is %.4f', [MantelHaenszel, MHprob]); + lReport.Add(''); + + CoefCont := sqrt(ChiSquare / (ChiSquare + NCases)); + lReport.Add('The coefficient of contingency is %.3f', [CoefCont]); + lReport.Add(''); + + if (Nrows < Ncols) then + CramerV := sqrt(ChiSquare / (NCases * ((NRows-1)))) + else + CramerV := sqrt(ChiSquare / (NCases * ((NCols-1)))); + lReport.Add('Cramers V is %.3f', [CramerV]); + lReport.Add(''); + end; + + FReportFrame.DisplayReport(lReport); + finally + lReport.Free; + end; + + // save frequency data file if elected + if SaveFChk.Checked then + begin + OS3MainFrm.mnuFileCloseClick(self); + OS3MainFrm.FileNameEdit.Text := ''; + for i := 1 to DictionaryFrm.DictGrid.RowCount - 1 do + for j := 0 to 7 do DictionaryFrm.DictGrid.Cells[j,i] := ''; + DictionaryFrm.DictGrid.RowCount := 1; + // DictionaryFrm.FileNameEdit.Text := ''; + + // get labels for new file + ColLabels[0] := 'ROW'; + ColLabels[1] := 'COL'; + ColLabels[2] := 'FREQ'; + // create new variables + Row := 0; + OS3MainFrm.DataGrid.ColCount := 4; + DictionaryFrm.DictGrid.ColCount := 8; + NoVariables := 0; + for i := 1 to 3 do + begin + col := NoVariables + 1; + DictionaryFrm.NewVar(col); + DictionaryFrm.DictGrid.Cells[1,col] := ColLabels[i-1]; + OS3MainFrm.DataGrid.Cells[col,0] := ColLabels[i-1]; + NoVariables := NoVariables + 1; + end; + OS3MainFrm.DataGrid.RowCount := (Nrows * NCols) + 1; + for i := 1 to Nrows do + begin + for j := 1 to Ncols do + begin + Row := Row + 1; + OS3MainFrm.DataGrid.Cells[0,Row] := Format('Case:%d',[Row]); + OS3MainFrm.DataGrid.Cells[1,Row] := IntToStr(i); + OS3MainFrm.DataGrid.Cells[2,Row] := IntToStr(j); + OS3MainFrm.DataGrid.Cells[3,Row] := IntToStr(Freq[i-1,j-1]); + end; + end; + NoCases := Row; + OS3MainFrm.FileNameEdit.Text := 'ChiSqrFreq.LAZ'; + OS3MainFrm.NoCasesEdit.Text := IntToStr(NoCases); + OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables); + // OS3MainFrm.SaveFileBtnClick(self); + end; + + //clean up + ColLabels := nil; + RowLabels := nil; + CellChi := nil; + Expected := nil; + Prop := nil; + Freq := nil; + ColNoSelected := nil; end; @@ -548,6 +642,10 @@ begin CellChiChk.Checked := false; SaveFChk.Checked := false; + FrequenciesPage.TabVisible := false; + RowColPage.TabVisible := false; + CellChiSqrPage.TabVisible := false; + UpdateBtnStates; end; diff --git a/applications/lazstats/source/forms/misc/basicstatsreportformunit.pas b/applications/lazstats/source/forms/misc/basicstatsreportformunit.pas index d4e2f5513..720e61da0 100644 --- a/applications/lazstats/source/forms/misc/basicstatsreportformunit.pas +++ b/applications/lazstats/source/forms/misc/basicstatsreportformunit.pas @@ -40,6 +40,7 @@ begin inherited; FReportFrame := TReportFrame.Create(self); + FReportFrame.Name := ''; FReportFrame.Parent := Self; FReportFrame.Align := alClient; FReportFrame.BorderSpacing.Left := 4; diff --git a/applications/lazstats/source/frames/reportframeunit.pas b/applications/lazstats/source/frames/reportframeunit.pas index 10330488b..aebc059c4 100644 --- a/applications/lazstats/source/frames/reportframeunit.pas +++ b/applications/lazstats/source/frames/reportframeunit.pas @@ -57,8 +57,8 @@ const constructor TReportFrame.Create(AOwner: TComponent); begin - Name := ''; inherited; + Name := ''; ReportPanel.Color := ReportMemo.Color; UpdateBtnStates; end;