diff --git a/applications/lazstats/LazStats.ini b/applications/lazstats/LazStats.ini index d8dce33fc..1c0b9eaa8 100644 --- a/applications/lazstats/LazStats.ini +++ b/applications/lazstats/LazStats.ini @@ -64,3 +64,4 @@ correlation, means, standard deviations and confidence interval for each correla 160=Correspondence analysis is a method for examining the relationship between two sets of categorical variables much as in a Chi-Squared analysis of a two-way contingency table. In fact, a typical chi-squared analysis is completed as part of this procedure. In addition, visualization of the relationships among the columns or rows of the analysis is performed in a manner similar to factor analysis. The data analyzed in the visualization is the table of relative proportions, that is, the original frequency values divided by the sum of all frequencies. The relative proportions of the row sums and the column sums are termed the “masses” of the rows or columns. The method used to analyze the relative proportions involves what is now called the “Generalized Singular Value Decomposition” or more simply the generalized SVD. This method obtains roots and vectors of a rectangular matrix by decomposing that matrix into three portions: a matrix of left singular column vectors (A) that has n rows and q columns (n ³ q), a square diagonal matrix with q rows and columns of singular values (D), and a transposed matrix (B’) that is m x q in size of right generalized singular vectors (m = q-1). Completing this analysis involves several steps. The first is to obtain the (regular) SVD analysis of a matrix Q defined as Dr-1/2PDc -1/2 where Dr and Dc are diagonal matrices of row and column relative proportions and P is the matrix of relative proportions. The SVD of Q gives Q = U D V’ where D is the desired diagonal matrix of eigenvalues and U’U = V’V = I. It should be noted that the first of the q roots is trivial and to be ignored. At this point we obtain A = Dr1/2U and B = Dc 1/2 V. The results of this SVD analysis is available on the output. Now P = ADB’. The row coordinates F and column coordinates G are then computed according to the table: Analysis Choice Button Selected Row Coordinates Column Coordinates Row Profile Row F = Dr-1AD G = Dc-1B Column Profile Column F = Dr-1A G = Dc-1BD Both Profiles Both F = Dr-1AD G = Dc-1BD If Row profiles are computed, the row coordinates are weighted centroids of the column coordinates and the inertias D2 refer only to the row points. If the column profiles are computed, the column coordinates are weighted eentroids of the row coordinates and the inertias D2 refer only to the column points. If both profiles are selected, neither row or column coordinates are weighted centroids of the other but the inertias D2 refer to both sets of points. The q-1 inertias are plotted in a manner similar to a scree plot of roots in a factor analysis. The total inertia is, in fact, the chi-squared statistic divided by the total of all cell frequencies. You may elect to plot the coordinates for any two pairs of coordinates. This will provide a graphical representation of the separation of the row or column categories similar to a plot of variables in a discriminant function analysis or factors in a factor analysis. A way of looking at correspondence analysis is to consider it as a method for decomposing the overall inertia by identifying a small number of dimensions in which the deviations from the expected values can be represented. This is similar to factor analysis where the total variance is decomposed so as to arrive at a lower dimensional representation of variables. 161=Directions:\n(1) Select the X variable common to all of the Y variables to be selected.\n(2) Select the Y variables.\n(3) Enter a label for the plot.\n(4) Select the options desired.\n(5) Click the Compute button to obtain results. 162=This procedure plots the frequency of cases in each of the groups in a group variable. The group variable should be defined as an integer variable.\n\nSelect the variable and type of plot and click the Compute button for the results. +163=The Resistant Line procedure creates three equal groups by sorting on the X variable and obtaining the median value of each group.\nThe median values for these three groups on both the X and Y variables are then plotted. The line from the low group median to the middle group median is plotted as well as the line from the middle group to the top group median. A comparison of the slope of these two lines gives an indication of the degree to which the data fit a straight line. Enter the X and Y variables to be analyzed and click the compute button. diff --git a/applications/lazstats/source/forms/analysis/descriptive/normalityunit.pas b/applications/lazstats/source/forms/analysis/descriptive/normalityunit.pas index 018972716..58114e0f7 100644 --- a/applications/lazstats/source/forms/analysis/descriptive/normalityunit.pas +++ b/applications/lazstats/source/forms/analysis/descriptive/normalityunit.pas @@ -126,6 +126,8 @@ begin Grid.Color := clSilver; Grid.Style := psSolid; end; + + PageControl.ActivePage := ChartPage; end; diff --git a/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.lfm b/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.lfm index 2b42da7f2..e2bbdc0d1 100644 --- a/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.lfm +++ b/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.lfm @@ -19,17 +19,17 @@ inherited PlotXYFrm: TPlotXYFrm TabOrder = 11 end inherited ComputeBtn: TButton - Left = 238 + Left = 237 Top = 459 TabOrder = 10 end inherited ResetBtn: TButton - Left = 176 + Left = 175 Top = 459 TabOrder = 9 end inherited HelpBtn: TButton - Left = 117 + Left = 116 Top = 459 TabOrder = 8 end diff --git a/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.pas b/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.pas index 5df025b9c..6ac196fde 100644 --- a/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.pas +++ b/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.pas @@ -39,18 +39,19 @@ type procedure XOutBtnClick(Sender: TObject); procedure YInBtnClick(Sender: TObject); procedure YOutBtnClick(Sender: TObject); + private - { private declarations } procedure PlotXY(XPoints, YPoints, UpConf, LowConf: DblDyneVec; XMean, YMean, R, Slope, Intercept: Double); + protected procedure AdjustConstraints; override; procedure Compute; override; procedure UpdateBtnStates; override; function Validate(out AMsg: String; out AControl: TWinControl; Xcol,Ycol: Integer): Boolean; reintroduce; + public - { public declarations } constructor Create(AOwner: TComponent); override; procedure Reset; override; end; @@ -82,6 +83,7 @@ begin Marks.Source := TListChartSource.Create(self); Marks.Style := smsLabel; Grid.Visible := false; + TickColor := clNone; end; with FChartFrame.Chart.AxisList.Add do begin @@ -89,6 +91,7 @@ begin Marks.Source := TListChartSource.Create(self); Marks.Style := smsLabel; Grid.Visible := false; + TickColor := clNone; end; PageControl.ActivePage := ChartPage; @@ -204,7 +207,7 @@ begin t := InverseT(confBand, DF); for i := 0 to N-1 do begin - predicted := slope * xValues[i] + intercept; + predicted := intercept + slope * xValues[i]; seData := sePred * sqrt(1.0 + 1/N + sqr(xValues[i] - XMean) / SXX); upConf[i] := predicted + t * seData; lowConf[i] := predicted - t * seData; diff --git a/applications/lazstats/source/forms/analysis/descriptive/resistancelineunit.lfm b/applications/lazstats/source/forms/analysis/descriptive/resistancelineunit.lfm index 19f70d04a..5bda8c087 100644 --- a/applications/lazstats/source/forms/analysis/descriptive/resistancelineunit.lfm +++ b/applications/lazstats/source/forms/analysis/descriptive/resistancelineunit.lfm @@ -1,571 +1,507 @@ -object ResistanceLineForm: TResistanceLineForm +inherited ResistanceLineForm: TResistanceLineForm Left = 581 - Height = 480 + Height = 438 Top = 301 - Width = 535 + Width = 883 HelpType = htKeyword HelpKeyword = 'html/ResistantLineforBivariateData.htm' Caption = 'Resistant Line for Bivariate Data' - ClientHeight = 480 - ClientWidth = 535 - OnActivate = FormActivate - OnCreate = FormCreate - OnShow = ResetBtnClick - Position = poMainFormCenter - LCLVersion = '2.0.10.0' - object Label1: TLabel - AnchorSideLeft.Control = Owner - AnchorSideTop.Control = HorCenterBevel - AnchorSideTop.Side = asrBottom - Left = 8 - Height = 15 - Top = 144 - Width = 46 - BorderSpacing.Left = 8 - Caption = 'Variables' - ParentColor = False - end - object Label2: TLabel - AnchorSideLeft.Control = XEdit - AnchorSideTop.Control = Label1 - Left = 188 - Height = 15 - Top = 144 - Width = 93 - Caption = 'Selected Variables' - ParentColor = False - end - object Label3: TLabel - AnchorSideLeft.Control = XEdit - AnchorSideBottom.Control = XEdit - Left = 188 - Height = 15 - Top = 183 - Width = 51 - Anchors = [akLeft, akBottom] - BorderSpacing.Bottom = 2 - Caption = 'X Variable' - ParentColor = False - end - object Label4: TLabel - AnchorSideLeft.Control = YEdit - AnchorSideBottom.Control = YEdit - Left = 188 - Height = 15 - Top = 300 - Width = 51 - Anchors = [akLeft, akBottom] - BorderSpacing.Bottom = 2 - Caption = 'Y Variable' - ParentColor = False - end - object XEdit: TEdit - AnchorSideLeft.Control = XInBtn - AnchorSideLeft.Side = asrBottom - AnchorSideRight.Control = GroupBox1 - AnchorSideBottom.Control = XOutBtn - AnchorSideBottom.Side = asrBottom - Left = 188 - Height = 23 - Top = 200 - Width = 136 - Anchors = [akLeft, akRight, akBottom] - BorderSpacing.Right = 16 - BorderSpacing.Bottom = 12 - ReadOnly = True - TabOrder = 3 - Text = 'XEdit' - end - object YEdit: TEdit - AnchorSideLeft.Control = XEdit - AnchorSideRight.Control = XEdit - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = YOutBtn - AnchorSideBottom.Side = asrBottom - Left = 188 - Height = 23 - Top = 317 - Width = 136 - Anchors = [akLeft, akRight, akBottom] - BorderSpacing.Bottom = 12 - ReadOnly = True - TabOrder = 6 - Text = 'Edit1' - end - object XInBtn: TBitBtn - AnchorSideLeft.Control = HorCenterBevel - AnchorSideLeft.Side = asrCenter - AnchorSideRight.Control = XEdit - AnchorSideBottom.Control = XOutBtn - Left = 152 - Height = 28 - Top = 175 - Width = 28 - Anchors = [akLeft, akBottom] - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 4 - Glyph.Data = { - 36040000424D3604000000000000360000002800000010000000100000000100 - 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00216324B81D5E2006FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF002A702F38256929F7216324D9FFFFFF00FFFFFF00FFFFFF00FFFFFF0061BE - 6DFF5DB868FF58B162FF53A95CFF4DA156FF47994FFF419149FF3B8842FF3580 - 3BFF3F8845FF59A15EFF448B49FF216324CFFFFFFF00FFFFFF00FFFFFF0065C3 - 71FFA0D7A9FF9CD5A5FF98D3A1FF94D09DFF90CE98FF8BCB93FF87C98EFF82C6 - 89FF7EC384FF7AC180FF76BE7CFF458C4AFF216324C4FFFFFF00FFFFFF0068C7 - 74FFA5DAAEFFA2D8ABFF9ED6A7FF9AD4A3FF96D29FFF93CF9AFF8ECC95FF89CA - 90FF85C78BFF81C587FF7DC282FF4A9150FF256929C9FFFFFF00FFFFFF0068C7 - 74FF68C774FF65C371FF61BE6DFF5DB868FF58B162FF53A95CFF4DA156FF4799 - 4FFF419149FF5AA362FF559D5CFF2F7835D1FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00419149F73B8842DBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF0047994FBB41914906FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 - } - Images = MainDataModule.ImageList - ImageIndex = 1 - OnClick = XInBtnClick - Spacing = 0 - TabOrder = 1 - end - object YInBtn: TBitBtn - AnchorSideLeft.Control = HorCenterBevel - AnchorSideLeft.Side = asrCenter - AnchorSideTop.Control = Bevel1 - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = YEdit - Left = 152 - Height = 28 - Top = 292 - Width = 28 - BorderSpacing.Right = 8 - Glyph.Data = { - 36040000424D3604000000000000360000002800000010000000100000000100 - 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00216324B81D5E2006FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF002A702F38256929F7216324D9FFFFFF00FFFFFF00FFFFFF00FFFFFF0061BE - 6DFF5DB868FF58B162FF53A95CFF4DA156FF47994FFF419149FF3B8842FF3580 - 3BFF3F8845FF59A15EFF448B49FF216324CFFFFFFF00FFFFFF00FFFFFF0065C3 - 71FFA0D7A9FF9CD5A5FF98D3A1FF94D09DFF90CE98FF8BCB93FF87C98EFF82C6 - 89FF7EC384FF7AC180FF76BE7CFF458C4AFF216324C4FFFFFF00FFFFFF0068C7 - 74FFA5DAAEFFA2D8ABFF9ED6A7FF9AD4A3FF96D29FFF93CF9AFF8ECC95FF89CA - 90FF85C78BFF81C587FF7DC282FF4A9150FF256929C9FFFFFF00FFFFFF0068C7 - 74FF68C774FF65C371FF61BE6DFF5DB868FF58B162FF53A95CFF4DA156FF4799 - 4FFF419149FF5AA362FF559D5CFF2F7835D1FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00419149F73B8842DBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF0047994FBB41914906FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 - } - Images = MainDataModule.ImageList - ImageIndex = 1 - OnClick = YInBtnClick - Spacing = 0 - TabOrder = 4 - end - object XOutBtn: TBitBtn - AnchorSideLeft.Control = XInBtn - AnchorSideBottom.Control = Bevel1 - Left = 152 - Height = 28 - Top = 207 - Width = 28 - Anchors = [akLeft, akBottom] - Glyph.Data = { - 36040000424D3604000000000000360000002800000010000000100000000100 - 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF004DA1560647994FB8FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF0053A95CD94DA156F747994F38FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF005DB868CF71BE7BFF7AC183FF5BAA64FF47994FFF419149FF3B8842FF3580 - 3BFF2F7835FF2A702FFF256929FF216324FF1D5E20FFFFFFFF00FFFFFF0065C3 - 71C47BC886FF9CD5A5FF98D3A1FF94D09DFF90CE98FF8BCB93FF87C98EFF82C6 - 89FF7EC384FF7AC180FF76BE7CFF72BD78FF216324FFFFFFFF00FFFFFF0068C7 - 74C97FCC8AFFA2D8ABFF9ED6A7FF9AD4A3FF96D29FFF93CF9AFF8ECC95FF89CA - 90FF85C78BFF81C587FF7DC282FF78C07EFF256929FFFFFFFF00FFFFFF00FFFF - FF0068C774D180CD8BFF7CC987FF5DB868FF58B162FF53A95CFF4DA156FF4799 - 4FFF419149FF3B8842FF35803BFF2F7835FF2A702FFFFFFFFF00FFFFFF00FFFF - FF00FFFFFF0068C774DB65C371F7FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF0068C7740668C774BBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 - } - Images = MainDataModule.ImageList - ImageIndex = 0 - OnClick = XOutBtnClick - Spacing = 0 - TabOrder = 2 - end - object YOutBtn: TBitBtn - AnchorSideLeft.Control = YInBtn - AnchorSideTop.Control = YInBtn - AnchorSideTop.Side = asrBottom - Left = 152 - Height = 28 - Top = 324 - Width = 28 - BorderSpacing.Top = 4 - Glyph.Data = { - 36040000424D3604000000000000360000002800000010000000100000000100 - 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF004DA1560647994FB8FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF0053A95CD94DA156F747994F38FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF005DB868CF71BE7BFF7AC183FF5BAA64FF47994FFF419149FF3B8842FF3580 - 3BFF2F7835FF2A702FFF256929FF216324FF1D5E20FFFFFFFF00FFFFFF0065C3 - 71C47BC886FF9CD5A5FF98D3A1FF94D09DFF90CE98FF8BCB93FF87C98EFF82C6 - 89FF7EC384FF7AC180FF76BE7CFF72BD78FF216324FFFFFFFF00FFFFFF0068C7 - 74C97FCC8AFFA2D8ABFF9ED6A7FF9AD4A3FF96D29FFF93CF9AFF8ECC95FF89CA - 90FF85C78BFF81C587FF7DC282FF78C07EFF256929FFFFFFFF00FFFFFF00FFFF - FF0068C774D180CD8BFF7CC987FF5DB868FF58B162FF53A95CFF4DA156FF4799 - 4FFF419149FF3B8842FF35803BFF2F7835FF2A702FFFFFFFFF00FFFFFF00FFFF - FF00FFFFFF0068C774DB65C371F7FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF0068C7740668C774BBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 - } - Images = MainDataModule.ImageList - ImageIndex = 0 - OnClick = YOutBtnClick - Spacing = 0 - TabOrder = 5 - end - object ResetBtn: TButton - AnchorSideRight.Control = ComputeBtn - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 326 - Height = 25 - Top = 447 - Width = 54 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 12 - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Reset' - OnClick = ResetBtnClick - TabOrder = 11 - end - object ComputeBtn: TButton - AnchorSideRight.Control = CloseBtn - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 388 - Height = 25 - Top = 447 - Width = 76 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Compute' - OnClick = ComputeBtnClick - TabOrder = 12 - end - object CloseBtn: TButton - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 472 - Height = 25 - Top = 447 - Width = 55 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Close' - ModalResult = 11 - OnClick = CloseBtnClick - TabOrder = 13 - end - object GroupBox1: TGroupBox - AnchorSideTop.Control = Label1 - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - Left = 340 - Height = 152 - Top = 144 - Width = 187 - Anchors = [akTop, akRight] - AutoSize = True - BorderSpacing.Right = 8 - Caption = 'Options' - ClientHeight = 132 - ClientWidth = 183 - Enabled = False - TabOrder = 7 - object Label5: TLabel - AnchorSideLeft.Control = GroupBox1 - AnchorSideTop.Control = ConfEdit - AnchorSideTop.Side = asrCenter - Left = 32 + ClientHeight = 438 + ClientWidth = 883 + inherited ParamsPanel: TPanel + Height = 422 + Width = 320 + ClientHeight = 422 + ClientWidth = 320 + inherited CloseBtn: TButton + Left = 265 + Top = 397 + TabOrder = 11 + end + inherited ComputeBtn: TButton + Left = 181 + Top = 397 + TabOrder = 10 + end + inherited ResetBtn: TButton + Left = 119 + Top = 397 + TabOrder = 9 + end + inherited HelpBtn: TButton + Tag = 163 + Left = 60 + Top = 397 + TabOrder = 8 + end + inherited ButtonBevel: TBevel + Top = 381 + Width = 320 + end + object Label1: TLabel[5] + AnchorSideLeft.Control = VarList + AnchorSideTop.Control = ParamsPanel + Left = 8 Height = 15 - Top = 101 - Width = 74 - BorderSpacing.Left = 32 - Caption = '% Confidence' + Top = 0 + Width = 46 + Caption = 'Variables' ParentColor = False end - object DescChk: TCheckBox - AnchorSideLeft.Control = GroupBox1 - AnchorSideTop.Control = PointsChk - AnchorSideTop.Side = asrBottom - Left = 12 - Height = 19 + object Label2: TLabel[6] + AnchorSideLeft.Control = XEdit + AnchorSideTop.Control = Label1 + Left = 181 + Height = 15 + Top = 0 + Width = 93 + Caption = 'Selected Variables' + ParentColor = False + end + object Label3: TLabel[7] + AnchorSideLeft.Control = XEdit + AnchorSideBottom.Control = XEdit + Left = 181 + Height = 15 Top = 21 - Width = 155 - BorderSpacing.Left = 12 - Caption = 'Print Descriptive Statistics' + Width = 51 + Anchors = [akLeft, akBottom] + BorderSpacing.Bottom = 2 + Caption = 'X Variable' + ParentColor = False + end + object Label4: TLabel[8] + AnchorSideLeft.Control = YEdit + AnchorSideBottom.Control = YEdit + Left = 181 + Height = 15 + Top = 101 + Width = 51 + Anchors = [akLeft, akBottom] + BorderSpacing.Bottom = 2 + Caption = 'Y Variable' + ParentColor = False + end + object XEdit: TEdit[9] + AnchorSideLeft.Control = XInBtn + AnchorSideLeft.Side = asrBottom + AnchorSideRight.Control = ParamsPanel + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = XOutBtn + AnchorSideBottom.Side = asrBottom + Left = 181 + Height = 23 + Top = 38 + Width = 139 + Anchors = [akLeft, akRight, akBottom] + BorderSpacing.Bottom = 12 + ReadOnly = True + TabOrder = 3 + Text = 'XEdit' + end + object YEdit: TEdit[10] + AnchorSideLeft.Control = XEdit + AnchorSideRight.Control = XEdit + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = YOutBtn + AnchorSideBottom.Side = asrBottom + Left = 181 + Height = 23 + Top = 118 + Width = 139 + Anchors = [akLeft, akRight, akBottom] + BorderSpacing.Bottom = 12 + ReadOnly = True + TabOrder = 6 + Text = 'YEdit' + end + object XInBtn: TBitBtn[11] + AnchorSideLeft.Control = ParamsPanel + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = VarList + AnchorSideRight.Control = XEdit + AnchorSideBottom.Control = XOutBtn + Left = 147 + Height = 26 + Top = 17 + Width = 26 + BorderSpacing.Right = 8 + BorderSpacing.Bottom = 4 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00216324B81D5E2006FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF002A702F38256929F7216324D9FFFFFF00FFFFFF00FFFFFF00FFFFFF0061BE + 6DFF5DB868FF58B162FF53A95CFF4DA156FF47994FFF419149FF3B8842FF3580 + 3BFF3F8845FF59A15EFF448B49FF216324CFFFFFFF00FFFFFF00FFFFFF0065C3 + 71FFA0D7A9FF9CD5A5FF98D3A1FF94D09DFF90CE98FF8BCB93FF87C98EFF82C6 + 89FF7EC384FF7AC180FF76BE7CFF458C4AFF216324C4FFFFFF00FFFFFF0068C7 + 74FFA5DAAEFFA2D8ABFF9ED6A7FF9AD4A3FF96D29FFF93CF9AFF8ECC95FF89CA + 90FF85C78BFF81C587FF7DC282FF4A9150FF256929C9FFFFFF00FFFFFF0068C7 + 74FF68C774FF65C371FF61BE6DFF5DB868FF58B162FF53A95CFF4DA156FF4799 + 4FFF419149FF5AA362FF559D5CFF2F7835D1FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00419149F73B8842DBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0047994FBB41914906FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + Images = MainDataModule.ImageList + ImageIndex = 1 + OnClick = XInBtnClick + Spacing = 0 TabOrder = 1 end - object ConfEdit: TEdit - AnchorSideLeft.Control = Label5 - AnchorSideLeft.Side = asrBottom - AnchorSideTop.Control = ConfChk + object YInBtn: TBitBtn[12] + AnchorSideLeft.Control = ParamsPanel + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = XOutBtn AnchorSideTop.Side = asrBottom - Left = 114 - Height = 23 + AnchorSideRight.Control = YEdit + Left = 147 + Height = 26 Top = 97 - Width = 57 - Alignment = taRightJustify - BorderSpacing.Left = 8 - BorderSpacing.Right = 12 - BorderSpacing.Bottom = 12 - TabOrder = 5 - Text = '95.0' - end - object LineChk: TCheckBox - AnchorSideLeft.Control = GroupBox1 - AnchorSideTop.Control = DescChk - AnchorSideTop.Side = asrBottom - Left = 12 - Height = 19 - Top = 40 - Width = 146 - BorderSpacing.Left = 12 - Caption = 'Plot the Regression Line' - TabOrder = 2 - end - object MeansChk: TCheckBox - AnchorSideLeft.Control = GroupBox1 - AnchorSideTop.Control = LineChk - AnchorSideTop.Side = asrBottom - Left = 12 - Height = 19 - Top = 59 - Width = 99 - BorderSpacing.Left = 12 - Caption = 'Plot the Means' - TabOrder = 3 - end - object ConfChk: TCheckBox - AnchorSideLeft.Control = GroupBox1 - AnchorSideTop.Control = MeansChk - AnchorSideTop.Side = asrBottom - Left = 12 - Height = 19 - Top = 78 - Width = 155 - BorderSpacing.Left = 12 - Caption = 'Plot the Confidence Band' + Width = 26 + BorderSpacing.Top = 24 + BorderSpacing.Right = 8 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00216324B81D5E2006FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF002A702F38256929F7216324D9FFFFFF00FFFFFF00FFFFFF00FFFFFF0061BE + 6DFF5DB868FF58B162FF53A95CFF4DA156FF47994FFF419149FF3B8842FF3580 + 3BFF3F8845FF59A15EFF448B49FF216324CFFFFFFF00FFFFFF00FFFFFF0065C3 + 71FFA0D7A9FF9CD5A5FF98D3A1FF94D09DFF90CE98FF8BCB93FF87C98EFF82C6 + 89FF7EC384FF7AC180FF76BE7CFF458C4AFF216324C4FFFFFF00FFFFFF0068C7 + 74FFA5DAAEFFA2D8ABFF9ED6A7FF9AD4A3FF96D29FFF93CF9AFF8ECC95FF89CA + 90FF85C78BFF81C587FF7DC282FF4A9150FF256929C9FFFFFF00FFFFFF0068C7 + 74FF68C774FF65C371FF61BE6DFF5DB868FF58B162FF53A95CFF4DA156FF4799 + 4FFF419149FF5AA362FF559D5CFF2F7835D1FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00419149F73B8842DBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0047994FBB41914906FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + Images = MainDataModule.ImageList + ImageIndex = 1 + OnClick = YInBtnClick + Spacing = 0 TabOrder = 4 end - object PointsChk: TCheckBox - AnchorSideLeft.Control = GroupBox1 - AnchorSideTop.Control = GroupBox1 - Left = 12 - Height = 19 - Top = 2 - Width = 153 - BorderSpacing.Left = 12 + object XOutBtn: TBitBtn[13] + AnchorSideLeft.Control = XInBtn + AnchorSideTop.Control = XInBtn + AnchorSideTop.Side = asrBottom + Left = 147 + Height = 26 + Top = 47 + Width = 26 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF004DA1560647994FB8FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0053A95CD94DA156F747994F38FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF005DB868CF71BE7BFF7AC183FF5BAA64FF47994FFF419149FF3B8842FF3580 + 3BFF2F7835FF2A702FFF256929FF216324FF1D5E20FFFFFFFF00FFFFFF0065C3 + 71C47BC886FF9CD5A5FF98D3A1FF94D09DFF90CE98FF8BCB93FF87C98EFF82C6 + 89FF7EC384FF7AC180FF76BE7CFF72BD78FF216324FFFFFFFF00FFFFFF0068C7 + 74C97FCC8AFFA2D8ABFF9ED6A7FF9AD4A3FF96D29FFF93CF9AFF8ECC95FF89CA + 90FF85C78BFF81C587FF7DC282FF78C07EFF256929FFFFFFFF00FFFFFF00FFFF + FF0068C774D180CD8BFF7CC987FF5DB868FF58B162FF53A95CFF4DA156FF4799 + 4FFF419149FF3B8842FF35803BFF2F7835FF2A702FFFFFFFFF00FFFFFF00FFFF + FF00FFFFFF0068C774DB65C371F7FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0068C7740668C774BBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + Images = MainDataModule.ImageList + ImageIndex = 0 + OnClick = XOutBtnClick + Spacing = 0 + TabOrder = 2 + end + object YOutBtn: TBitBtn[14] + AnchorSideLeft.Control = YInBtn + AnchorSideTop.Control = YInBtn + AnchorSideTop.Side = asrBottom + Left = 147 + Height = 26 + Top = 127 + Width = 26 + BorderSpacing.Top = 4 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF004DA1560647994FB8FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0053A95CD94DA156F747994F38FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF005DB868CF71BE7BFF7AC183FF5BAA64FF47994FFF419149FF3B8842FF3580 + 3BFF2F7835FF2A702FFF256929FF216324FF1D5E20FFFFFFFF00FFFFFF0065C3 + 71C47BC886FF9CD5A5FF98D3A1FF94D09DFF90CE98FF8BCB93FF87C98EFF82C6 + 89FF7EC384FF7AC180FF76BE7CFF72BD78FF216324FFFFFFFF00FFFFFF0068C7 + 74C97FCC8AFFA2D8ABFF9ED6A7FF9AD4A3FF96D29FFF93CF9AFF8ECC95FF89CA + 90FF85C78BFF81C587FF7DC282FF78C07EFF256929FFFFFFFF00FFFFFF00FFFF + FF0068C774D180CD8BFF7CC987FF5DB868FF58B162FF53A95CFF4DA156FF4799 + 4FFF419149FF3B8842FF35803BFF2F7835FF2A702FFFFFFFFF00FFFFFF00FFFF + FF00FFFFFF0068C774DB65C371F7FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0068C7740668C774BBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + Images = MainDataModule.ImageList + ImageIndex = 0 + OnClick = YOutBtnClick + Spacing = 0 + TabOrder = 5 + end + object OptionsGroup: TGroupBox[15] + AnchorSideLeft.Control = ParamsPanel + AnchorSideTop.Control = Label1 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = ButtonBevel + Left = 0 + Height = 228 + Top = 153 + Width = 264 + Anchors = [akLeft, akBottom] + AutoSize = True + BorderSpacing.Right = 8 + Caption = 'Options' + ClientHeight = 208 + ClientWidth = 260 + TabOrder = 7 + object ConfLabel: TLabel + AnchorSideLeft.Control = OptionsGroup + AnchorSideTop.Control = ConfEdit + AnchorSideTop.Side = asrCenter + Left = 32 + Height = 15 + Top = 131 + Width = 74 + BorderSpacing.Left = 32 + Caption = '% Confidence' + ParentColor = False + end + object DescChk: TCheckBox + AnchorSideLeft.Control = OptionsGroup + AnchorSideTop.Control = ConfEdit + AnchorSideTop.Side = asrBottom + Left = 12 + Height = 19 + Top = 158 + Width = 153 + BorderSpacing.Left = 12 + Caption = 'Print descriptive statistics' + TabOrder = 7 + end + object ConfEdit: TEdit + AnchorSideLeft.Control = ConfLabel + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = ConfChk + AnchorSideTop.Side = asrBottom + Left = 114 + Height = 23 + Top = 127 + Width = 57 + Alignment = taRightJustify + BorderSpacing.Left = 8 + BorderSpacing.Right = 12 + BorderSpacing.Bottom = 8 + TabOrder = 5 + Text = '95.0' + end + object LineChk: TCheckBox + AnchorSideLeft.Control = OptionsGroup + AnchorSideTop.Control = OptionsBevel + AnchorSideTop.Side = asrBottom + Left = 12 + Height = 19 + Top = 70 + Width = 146 + BorderSpacing.Left = 12 + BorderSpacing.Top = 12 + Caption = 'Plot the Regression Line' + TabOrder = 2 + end + object MeansChk: TCheckBox + AnchorSideLeft.Control = OptionsGroup + AnchorSideTop.Control = LineChk + AnchorSideTop.Side = asrBottom + Left = 12 + Height = 19 + Top = 89 + Width = 99 + BorderSpacing.Left = 12 + Caption = 'Plot the Means' + TabOrder = 3 + end + object ConfChk: TCheckBox + AnchorSideLeft.Control = OptionsGroup + AnchorSideTop.Control = MeansChk + AnchorSideTop.Side = asrBottom + Left = 12 + Height = 19 + Top = 108 + Width = 155 + BorderSpacing.Left = 12 + Caption = 'Plot the Confidence Band' + TabOrder = 4 + end + object GridChk: TCheckBox + AnchorSideLeft.Control = OptionsGroup + AnchorSideTop.Control = DescChk + AnchorSideTop.Side = asrBottom + Left = 12 + Height = 19 + Top = 177 + Width = 248 + BorderSpacing.Left = 12 + BorderSpacing.Bottom = 12 + Caption = 'Enter Predicted Y and Residual Y in the Grid' + TabOrder = 6 + end + object PlotMediansChk: TRadioButton + AnchorSideLeft.Control = OptionsGroup + AnchorSideTop.Control = OptionsGroup + Left = 12 + Height = 19 + Top = 6 + Width = 215 + BorderSpacing.Left = 12 + BorderSpacing.Top = 6 + Caption = 'Plot the three medians and slope line' + OnChange = PlotMediansChkChange + TabOrder = 0 + end + object PlotPointsChk: TRadioButton + AnchorSideLeft.Control = OptionsGroup + AnchorSideTop.Control = PlotMediansChk + AnchorSideTop.Side = asrBottom + Left = 12 + Height = 19 + Top = 27 + Width = 146 + BorderSpacing.Left = 12 + BorderSpacing.Top = 2 + Caption = 'Plot points and linear fit' + OnChange = PlotMediansChkChange + TabOrder = 1 + end + object OptionsBevel: TBevel + AnchorSideLeft.Control = OptionsGroup + AnchorSideTop.Control = PlotPointsChk + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = OptionsGroup + AnchorSideRight.Side = asrBottom + Left = 12 + Height = 12 + Top = 46 + Width = 236 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 12 + BorderSpacing.Right = 12 + Shape = bsBottomLine + end + end + object VarList: TListBox[16] + AnchorSideLeft.Control = ParamsPanel + AnchorSideTop.Control = Label1 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = XInBtn + AnchorSideBottom.Control = OptionsGroup + Left = 8 + Height = 128 + Top = 17 + Width = 131 + Anchors = [akTop, akLeft, akRight, akBottom] + BorderSpacing.Left = 8 BorderSpacing.Top = 2 - Caption = 'Plot All of the points First' + BorderSpacing.Right = 8 + BorderSpacing.Bottom = 8 + ItemHeight = 0 + OnDblClick = VarListDblClick + OnSelectionChange = VarListSelectionChange TabOrder = 0 end end - object VarList: TListBox - AnchorSideLeft.Control = Owner - AnchorSideTop.Control = Label1 - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = XInBtn - AnchorSideBottom.Control = StdCorChk - Left = 8 - Height = 205 - Top = 161 - Width = 136 - Anchors = [akTop, akLeft, akRight, akBottom] - BorderSpacing.Left = 8 - BorderSpacing.Top = 2 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Constraints.MinHeight = 200 - ItemHeight = 0 - OnSelectionChange = VarListSelectionChange - TabOrder = 0 + inherited ParamsSplitter: TSplitter + Left = 332 + Height = 438 end - object StdCorChk: TCheckBox - AnchorSideLeft.Control = Owner - AnchorSideBottom.Control = PlotMediansChk - Left = 8 - Height = 19 - Top = 374 - Width = 330 - Anchors = [akLeft, akBottom] - BorderSpacing.Left = 8 - Caption = 'Option: Compute a standard product-moment correlation.' - OnChange = StdCorChkChange - TabOrder = 8 - end - object PlotMediansChk: TCheckBox - AnchorSideLeft.Control = Owner - AnchorSideBottom.Control = GridChk - Left = 8 - Height = 19 - Top = 393 - Width = 265 - Anchors = [akLeft, akBottom] - BorderSpacing.Left = 8 - Caption = 'Plot the Three Medians and Slope Line (in Red)' - TabOrder = 9 - end - object GridChk: TCheckBox - AnchorSideLeft.Control = Owner - AnchorSideBottom.Control = Bevel2 - Left = 8 - Height = 19 - Top = 412 - Width = 248 - Anchors = [akLeft, akBottom] - BorderSpacing.Left = 8 - Caption = 'Enter Predicted Y and Residual Y in the Grid' - TabOrder = 10 - end - object Bevel1: TBevel - AnchorSideLeft.Control = YInBtn - AnchorSideLeft.Side = asrCenter - AnchorSideTop.Control = VarList - AnchorSideTop.Side = asrCenter - Left = 161 - Height = 57 - Top = 235 - Width = 10 - Shape = bsSpacer - end - object Bevel2: TBevel - AnchorSideLeft.Control = Owner - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - Left = 0 - Height = 8 - Top = 431 - Width = 535 - Anchors = [akLeft, akRight, akBottom] - Shape = bsBottomLine - end - object Memo1: TLabel - AnchorSideLeft.Control = Owner - AnchorSideTop.Control = Owner - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - Left = 8 - Height = 120 - Top = 8 - Width = 519 - Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 8 - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - Caption = 'The Resistant Line procedure creates three equal groups by sorting on the X variable and obtaining the median value of each group.'#13#10#13#10'The median values for these three groups on both the X and Y variables are then plotted. The line from the low group median to the middle group median is plotted as well as the line from the middle group to the top group median. A comparison of the slope of these two lines gives an indication of the degree to which the data fit a straight line. Enter the X and Y variables to be analyzed and click the compute button.' - ParentColor = False - WordWrap = True - end - object HorCenterBevel: TBevel - AnchorSideLeft.Control = VarList - AnchorSideTop.Control = Memo1 - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = XEdit - AnchorSideRight.Side = asrBottom - Left = 8 - Height = 16 - Top = 128 - Width = 316 - Anchors = [akTop, akLeft, akRight] - Shape = bsSpacer + inherited PageControl: TPageControl + Left = 341 + Height = 422 + Width = 534 end end diff --git a/applications/lazstats/source/forms/analysis/descriptive/resistancelineunit.pas b/applications/lazstats/source/forms/analysis/descriptive/resistancelineunit.pas index 61dc4e324..9e2c890ef 100644 --- a/applications/lazstats/source/forms/analysis/descriptive/resistancelineunit.pas +++ b/applications/lazstats/source/forms/analysis/descriptive/resistancelineunit.pas @@ -1,5 +1,8 @@ // Use file "Sickness.laz" for testing +// to do Not sure about the "red" slope line... +// to do: There are also two positions where a negative intercept is made positive. Why? Correct? + unit ResistanceLineUnit; {$mode objfpc}{$H+} @@ -7,35 +10,29 @@ unit ResistanceLineUnit; interface uses - Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, - StdCtrls, ExtCtrls, Buttons, Printers, + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, + StdCtrls, ExtCtrls, Buttons, Printers, ComCtrls, MainUnit, Globals, FunctionsLib, OutputUnit, DataProcs, DictionaryUnit, - ContextHelpUnit, BlankFrmUnit; + //BlankFrmUnit, + BasicStatsReportAndChartFormUnit; type { TResistanceLineForm } - TResistanceLineForm = class(TForm) - Bevel1: TBevel; - Bevel2: TBevel; - HorCenterBevel: TBevel; + TResistanceLineForm = class(TBasicStatsReportAndChartForm) + OptionsBevel: TBevel; GridChk: TCheckBox; - Memo1: TLabel; - PlotMediansChk: TCheckBox; - StdCorChk: TCheckBox; - PointsChk: TCheckBox; + PlotMediansChk: TRadioButton; ConfChk: TCheckBox; ConfEdit: TEdit; DescChk: TCheckBox; - GroupBox1: TGroupBox; - Label5: TLabel; + OptionsGroup: TGroupBox; + ConfLabel: TLabel; LineChk: TCheckBox; + PlotPointsChk: TRadioButton; VarList: TListBox; MeansChk: TCheckBox; - ResetBtn: TButton; - ComputeBtn: TButton; - CloseBtn: TButton; XInBtn: TBitBtn; YInBtn: TBitBtn; XOutBtn: TBitBtn; @@ -46,28 +43,42 @@ type Label2: TLabel; Label3: TLabel; Label4: TLabel; - procedure CloseBtnClick(Sender: TObject); - procedure ComputeBtnClick(Sender: TObject); - procedure FormActivate(Sender: TObject); - procedure FormCreate(Sender: TObject); - procedure ResetBtnClick(Sender: TObject); + procedure PlotMediansChkChange(Sender: TObject); procedure StdCorChkChange(Sender: TObject); - procedure VarListSelectionChange(Sender: TObject; User: boolean); + procedure VarListDblClick(Sender: TObject); + procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean); procedure XInBtnClick(Sender: TObject); procedure XOutBtnClick(Sender: TObject); procedure YInBtnClick(Sender: TObject); procedure YOutBtnClick(Sender: TObject); + private - { private declarations } - FAutoSized: Boolean; - function Median(var X: DblDyneVec; ASize: integer): double; - procedure PlotXY(const Xpoints, YPoints, UpConf, LowConf: DblDyneVec; - ConfBand, Xmean, Ymean, R, Slope, Intercept: double; - Xmax, Xmin, Ymax, Ymin: double; N, PlotNo: integer); - procedure UpdateBtnStates; + procedure PlotMedians(const XMedians, YMedians: DblDyneVec; + ASlope, AIntercept: Double); + procedure PlotXY(const XPoints, YPoints, UpConf, LowConf: DblDyneVec; + XMean, YMean, R, ASlope, AIntercept: Double); + + procedure ResidualsToGrid(xCol, yCol: Integer; + const AColNoSelected: IntDyneVec; Slope, Intercept: Double); + + procedure ResistantLineAnalysis(const xyPoints: DblDyneMat; + out XMedians, yMedians: DblDyneVec; out GrpSize: IntDyneVec); + + procedure WriteMedianReport(AReport: TStrings; + const XMedians, YMedians: DblDyneVec; const GrpSize: IntDyneVec; + Slope1, Slope2, Slope, Intercept: Double); + procedure WriteXYReport(AReport: TStrings; AFileName: String; + xMean, yMean, xVariance, yVariance, xStdDev, yStdDev, R, Slope, Intercept, SEPred: double; + N: Integer); + + protected + procedure AdjustConstraints; override; + procedure Compute; override; + procedure UpdateBtnStates; override; public - { public declarations } + constructor Create(AOwner: TComponent); override; + procedure Reset; override; end; var @@ -75,18 +86,308 @@ var implementation +{$R *.lfm} + uses - Math; + Math, Grids, + TATypes, TAChartUtils, TAChartAxisUtils, TALegend, TASources, TACustomSeries, + ChartFrameUnit, Utils, MathUnit, GridProcs; { TResistanceLineForm } -procedure TResistanceLineForm.ResetBtnClick(Sender: TObject); +constructor TResistanceLineForm.Create(AOwner: TComponent); +begin + inherited; + if DictionaryFrm = nil then Application.CreateForm(TDictionaryFrm, DictionaryFrm); + + FChartFrame.Chart.Legend.Alignment := laBottomCenter; + FChartFrame.Chart.Legend.ColumnCount := 3; + FChartFrame.Chart.Legend.TextFormat := tfHTML; + with FChartFrame.Chart.AxisList.Add do + begin + Alignment := calRight; + Marks.Source := TListChartSource.Create(self); + Marks.Style := smsLabel; + Grid.Visible := false; + TickColor := clNone; + end; + with FChartFrame.Chart.AxisList.Add do + begin + Alignment := calTop; + Marks.Source := TListChartSource.Create(self); + Marks.Style := smsLabel; + Grid.Visible := false; + TickColor := clNone; + end; + + PageControl.ActivePage := ChartPage; +end; + + +procedure TResistanceLineForm.AdjustConstraints; +begin + ParamsPanel.Constraints.MinHeight := YOutBtn.Top + YOutBtn.Height + + VarList.BorderSpacing.Bottom + OptionsGroup.Height + ButtonBevel.Height + + CloseBtn.Height; + + ParamsPanel.Constraints.MinWidth := Max( + 4*CloseBtn.Width + 3*CloseBtn.BorderSpacing.Left, + OptionsGroup.Width); +end; + + +procedure TResistanceLineForm.Compute; +var + xyPoints: DblDyneMat = nil; // 1st index: x or y, 2nd index: data index + xMedians: DblDyneVec = nil; + yMedians: DblDyneVec = nil; + colNoSelected : IntDyneVec = nil; + upConf: DblDyneVec = nil; + lowConf: DblDyneVec = nil; + grpSize: IntDyneVec = nil; + xCol, yCol: Integer; + i, N, DF: integer; + xMean, yMean, xVariance, yVariance, xStdDev, yStdDev, SXX, SXY, SYY, t: Double; + confBand, yPred: double; + R, SEPred, interceptFit, slopeFit, slope1, slope2, slopeRL, seData: double; + c, c1, c2, c3 : double; // constants obtained from control points + lReport: TStrings; + dataGrid: TStringGrid; +begin + dataGrid := OS3MainFrm.DataGrid; + + xCol := GetVariableIndex(dataGrid, XEdit.Text); + yCol := GetVariableIndex(dataGrid, YEdit.Text); + if xCol = -1 then + begin + ErrorMsg('X variable not specified or not found.'); + exit; + end; + if yCol = -1 then + begin + ErrorMsg('Y variable not specified or not found.'); + exit; + end; + + SetLength(colNoSelected, 2); + colNoSelected[0] := xCol; + colNoSelected[1] := yCol; + + // Get values from the grid + SetLength(xyPoints, 2); + xyPoints[0] := CollectValues(dataGrid, xCol, colNoSelected); + xyPoints[1] := CollectValues(dataGrid, ycol, colNoSelected); + N := Length(xyPoints[0]); + if N = 0 then + begin + ErrorMsg('No data points.'); + exit; + end; + if N <> Length(xyPoints[1]) then + begin + ErrorMsg('Equal count of cases required for x and y variables.'); + exit; + end; + + // Sort on the x values + SortOnX(xyPoints[0], xyPoints[1]); + + // Calculate means, variances, stddevs + Calc_MeanVarStdDevSS(xyPoints[0], xMean, xVariance, xStdDev, SXX); + Calc_MeanVarStdDevSS(xyPoints[1], yMean, yVariance, yStdDev, SYY); + + // Calculate linear fit of x vs y + SXY := 0; + for i := 0 to N-1 do + SXY := SXY + xyPoints[0, i] * xyPoints[1, i]; + + R := (SXY - xMean * yMean * N) / ((N - 1) * xStdDev * yStdDev); + sePred := sqrt(1.0 - sqr(R)) * yStdDev * sqrt((N - 1) / (N - 2)); + slopeFit := R * yStdDev / xStdDev; + interceptFit := yMean - slopeFit * xMean; + + // Get upper and lower confidence limits for each x value + if ConfChk.Checked then + begin + SetLength(upConf, N); + SetLength(lowConf, N); + confBand := StrToFloat(ConfEdit.Text) / 100.0; + DF := N - 2; + t := InverseT(ConfBand, DF); + for i := 0 to N-1 do + begin + yPred := interceptFit + slopeFit * xyPoints[0, i]; + seData := sePred * sqrt(1.0 + 1/N + sqr(xyPoints[0, i] - xMean)/SXX); + upConf[i] := yPred + t * seData; + lowConf[i] := yPred - t * seData; + end; + end; + + // Do the resistant line analysis + ResistantLineAnalysis(xyPoints, xMedians, yMedians, grpSize); + + slope1 := (yMedians[1] - yMedians[0]) / (xMedians[1] - xMedians[0]); + slope2 := (yMedians[2] - yMedians[1]) / (xMedians[2] - xMedians[1]); + slopeRL := (yMedians[2] - yMedians[0]) / (xMedians[2] - xMedians[0]); + + // obtain estimate of the constant for the prediction equation + c1 := slopeRL * xMedians[0] - yMedians[0]; + c2 := slopeRL * xMedians[1] - yMedians[1]; + c3 := slopeRL * xMedians[2] - yMedians[2]; + c := (c1 + c2 + c3) / 3.0; + if c < 0 then c := -c; // wp: why is this necessary? + + if GridChk.Checked then + ResidualsToGrid(xCol, yCol, colNoSelected, slopeRL, c); + + lReport := TStringList.Create; + try + WriteMedianReport(lReport, + xMedians, yMedians, grpSize, + slope1, slope2, slopeRL, c + ); + + if DescChk.Checked then + WriteXYReport(lReport, + OS3MainFrm.FileNameEdit.Text, + xMean, yMean, xVariance, yVariance, xStdDev, yStdDev, + R, slopeFit, interceptFit, sePred, + N + ); + + FReportFrame.DisplayReport(lReport); + finally + lReport.Free; + end; + + if PlotPointsChk.Checked then + PlotXY(xyPoints[0], xyPoints[1], upConf, lowConf, xMean, yMean, R, slopeFit, interceptFit); + + if PlotMediansChk.Checked then + PlotMedians(XMedians, YMedians, slopeRL, c); +end; + + +procedure TResistanceLineForm.PlotMedians(const XMedians, YMedians: DblDyneVec; + Aslope, AIntercept: Double); +var + ser: TChartSeries; + rightLabels: TListChartSource; + topLabels: TListChartSource; + labels: StrDyneVec = nil; + xpts: DblDyneVec = nil; + ypts: DblDyneVec = nil; + i: Integer; +begin + rightLabels := FChartFrame.Chart.AxisList[2].Marks.Source as TListChartSource; + rightLabels.Clear; + topLabels := FChartFrame.Chart.AxisList[3].Marks.Source as TListChartSource; + topLabels.Clear; + FChartFrame.Clear; + FChartFrame.Clear; + + FChartFrame.Chart.Margins.Left := 20; + FChartFrame.Chart.Margins.Right := 20; + + FChartFrame.SetTitle('Median plot for three groups'); + FChartFrame.SetFooter(Format('Slope = %.3f', [ASlope])); + FChartFrame.SetXTitle(XEdit.Text); + FChartFrame.SetYTitle(YEdit.Text); + + SetLength(labels, Length(XMedians)); + for i := 0 to High(XMedians) do + labels[i] := Format('M%d', [i+1]); + ser := FChartFrame.PlotXY(ptLinesAndSymbols, XMedians, YMedians, labels, nil, 'Medians', clNavy, psCircle); + ser.Marks.Style := smsLabel; + labels := nil; + + // Draw slope line + SetLength(xpts, 2); + SetLength(ypts, 2); + xpts[0] := XMedians[0]; + ypts[0] := AIntercept + ASlope * xpts[0]; + xpts[1] := XMedians[2]; + ypts[1] := AIntercept + ASlope * xpts[1]; + FChartFrame.PlotXY(ptLines, xpts, ypts, nil, nil, 'Slope line', clRed); +end; + + +procedure TResistanceLineForm.PlotXY(const XPoints, YPoints, UpConf, LowConf: DblDyneVec; + XMean, YMean, R, ASlope, AIntercept: Double); +var + ser: TChartSeries; + xPts: DblDyneVec = nil; + yPts: DblDyneVec = nil; + rightLabels: TListChartSource; + topLabels: TListChartSource; +begin + rightLabels := FChartFrame.Chart.AxisList[2].Marks.Source as TListChartSource; + rightLabels.Clear; + topLabels := FChartFrame.Chart.AxisList[3].Marks.Source as TListChartSource; + topLabels.Clear; + FChartFrame.Clear; + + FChartFrame.Chart.Margins.Left := 4; + FChartFrame.Chart.Margins.Right := 4; + + FChartFrame.SetTitle('X vs Y plot using file '+ OS3MainFrm.FileNameEdit.Text); + FChartFrame.SetFooter(Format('R(X,Y) = %.3f, Slope = %.2f, Intercept = %.2f', [R, ASlope, AIntercept])); + FChartFrame.SetXTitle(XEdit.Text); + FChartFrame.SetYTitle(YEdit.Text); + + // Draw means + if MeansChk.Checked then + begin + FChartFrame.VertLine(XMean, clGreen, psDashDot, 'Mean ' + XEdit.Text); + topLabels.Add(XMean, XMean, 'Mean ' + XEdit.Text); + + FChartFrame.HorLine(YMean, clGreen, psDash, 'Mean ' + YEdit.Text); + rightLabels.Add(YMean, YMean, 'Mean ' + YEdit.Text); + end; + + // Draw slope line + if LineChk.Checked then + begin + SetLength(xPts, 2); + SetLength(yPts, 2); + xPts[0] := XPoints[0]; + yPts[0] := AIntercept + XPoints[0] * ASlope; + xPts[1] := XPoints[High(XPoints)]; + yPts[1] := AIntercept + XPoints[High(XPoints)] * ASlope; + ser := FChartFrame.PlotXY(ptLines, xpts, ypts, nil, nil, 'Regression', clBlack); + rightLabels.Add(ser.XValue[ser.Count-1], ser.YValue[ser.Count-1], 'Regression'); + end; + + // Draw upper confidence band + if ConfChk.Checked then + begin + ser := FChartFrame.PlotXY(ptLines, XPoints, UpConf, nil, nil, 'Upper confidence band', clRed); + rightLabels.Add(ser.yValue[ser.Count-1], ser.YValue[ser.Count-1], 'UCL'); + end; + + // Draw lower confidence band + if ConfChk.Checked then + begin + ser := FChartFrame.PlotXY(ptLines, XPoints, LowConf, nil, nil, 'Lower confidence band', clRed); + rightLabels.Add(ser.yValue[ser.Count-1], ser.YValue[ser.Count-1], 'LCL'); + end; + + // Draw points for x and y pairs + ser := FChartFrame.PlotXY(ptSymbols, XPoints, YPoints, nil, nil, 'Data', clYellow, psCircle); + ser.Marks.Style := smsNone; +end; + + +procedure TResistanceLineForm.Reset; var i: integer; begin - StdCorChk.Checked := false; + inherited; + + PlotMediansChk.Checked := true; + PlotMediansChkChange(PlotMediansChk); GridChk.Checked := false; - PlotMediansChk.Checked := false; + XEdit.Text := ''; YEdit.Text := ''; VarList.Clear; @@ -94,331 +395,225 @@ begin for i := 1 to NoVariables do VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); UpdateBtnStates; + + if FReportFrame <> nil then FReportFrame.Clear; + if FChartFrame <> nil then FChartFrame.Clear; end; + +{ Get the residuals (Y - predicted Y) for each X value and place them in the grid } +procedure TResistanceLineForm.ResidualsToGrid(xCol, yCol: Integer; + const AColNoSelected: IntDyneVec; Slope, Intercept: Double); +var + s: String; + i: Integer; + x, y, yPred, yRes: Double; +begin + // New column for predicted value + s := 'Pred.' + OS3MainFrm.DataGrid.Cells[yCol, 0]; + DictionaryFrm.NewVar(NoVariables+1); + DictionaryFrm.DictGrid.Cells[1, NoVariables] := s; + OS3MainFrm.DataGrid.Cells[NoVariables, 0] := s; + + // New column for residual value + s := 'Residual'; + DictionaryFrm.NewVar(NoVariables+1); + DictionaryFrm.DictGrid.Cells[1, NoVariables] := s; + OS3MainFrm.DataGrid.Cells[NoVariables, 0] := s; + + for i := 1 to NoCases do + begin + if not DataProcs.GoodRecord(i, Length(AColNoSelected), AColNoSelected) then continue; + x := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[xCol, i])); + y := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[yCol, i])); + + // Calculate predicted value + if Intercept >= 0 then + yPred := Slope * x + Intercept // wp: why two equations? + else + yPred := Slope * x - Intercept; + + // Calculate residual + yRes := y - yPred; + + // Write to grid + OS3MainFrm.DataGrid.Cells[NoVariables-1, i] := Format('%.3f', [yPred]); + OS3MainFrm.DataGrid.Cells[NoVariables, i] := Format('%.3f', [yRes]); + end; +end; + +{ Do the resistant line analysis } +procedure TResistanceLineForm.ResistantLineAnalysis(const xyPoints: DblDyneMat; + out XMedians, yMedians: DblDyneVec; out GrpSize: IntDyneVec); +var + i, N, offs: Integer; + xVector: DblDyneVec = nil; + yVector: DblDyneVec = nil; +begin + N := Length(xyPoints[0]); + + GrpSize := nil; + XMedians := nil; + YMedians := nil; + + SetLength(GrpSize, 3); + SetLength(XMedians, 3); + SetLength(YMedians, 3); + + GrpSize[0] := N div 3; + GrpSize[2] := GrpSize[0]; + GrpSize[1] := N - GrpSize[0] - GrpSize[2]; + + // Sort the y values. The x values already are sorted. + //SortOnX(xyPoints[1]); + + // Get median for each group of x and y values + + // First group + SetLength(xVector, GrpSize[0]); + SetLength(yVector, GrpSize[0]); + offs := 0; + for i := 0 to GrpSize[1] - 1 do + begin + xVector[i] := xyPoints[0, i + offs]; + yVector[i] := xyPoints[1, i + offs]; + end; + xMedians[0] := Calc_Median(xVector); + yMedians[0] := Calc_Median(yVector); + + // Second group + SetLength(xVector, GrpSize[1]); + SetLength(yVector, GrpSize[1]); + offs := GrpSize[0]; + for i := 0 to GrpSize[1] - 1 do + begin + xVector[i] := xyPoints[0, i + offs]; + yVector[i] := xyPoints[1, i + offs]; + end; + xMedians[1] := Calc_Median(xVector); + yMedians[1] := Calc_Median(yVector); + + // Third group + SetLength(xVector, GrpSize[2]); + SetLength(yVector, GrpSize[2]); + offs := GrpSize[0] + GrpSize[1]; + for i := 0 to GrpSize[2] - 1 do + begin + xVector[i] := xyPoints[0, i + offs]; + yVector[i] := xyPoints[1, i + offs]; + end; + xMedians[2] := Calc_Median(xVector); + yMedians[2] := Calc_Median(yVector); +end; + + procedure TResistanceLineForm.StdCorChkChange(Sender: TObject); begin - if StdCorChk.Checked then GroupBox1.Enabled := true else GroupBox1.Enabled := false; + //if StdCorChk.Checked then OptionsGroup.Enabled := true else OptionsGroup.Enabled := false; end; -procedure TResistanceLineForm.ComputeBtnClick(Sender: TObject); +procedure TResistanceLineForm.PlotMediansChkChange(Sender: TObject); var - XYPoints : DblDyneMat; - XMedians : DblDyneVec; - YMedians : DblDyneVec; - XVector, YVector : DblDyneVec; - cellstring, outline : string; - ColNoSelected : IntDyneVec; - UpConf : DblDyneVec; - lowConf : DblDyneVec; - GrpSize : IntDyneVec; - Xcol, Ycol, N, NoSelected, i, j, size, size1, size2, size3 : integer; - X, Y, tempX, tempY : double; - Xmin, Xmax, Ymin, Ymax, SSx, t, DF : double; - Xmean, Ymean, Xvariance, Yvariance, Xstddev, Ystddev, ConfBand : double; - R, SEPred, Slope, Intercept, predicted, sedata : double; - slope1, slope2 : double; - c, c1, c2, c3 : double; // constants obtained from control points - lReport: TStrings; + enable: Boolean; begin - SetLength(XYPoints, NoCases, NoCases); - SetLength(XMedians, 3); - SetLength(YMedians, 3); - SetLength(XVector, NoCases); - SetLength(YVector, NoCases); - SetLength(ColNoSelected, NoVariables); - SetLength(UpConf, NoCases + 1); - SetLength(lowConf, NoCases + 1); - SetLength(GrpSize, 3); - Xcol := 0; - Ycol := 0; - Xmax := -1.0e20; - Xmin := 1.0e20; - Ymax := -1.0e20; - Ymin := 1.0e20; - Xmean := 0.0; - Ymean := 0.0; - Xvariance := 0.0; - Yvariance := 0.0; - R := 0.0; - - for i := 1 to Novariables do - begin - cellstring := OS3MainFrm.DataGrid.Cells[i,0]; - if cellstring = XEdit.Text then Xcol := i; - if cellstring = YEdit.Text then Ycol := i; - end; - NoSelected := 2; - ColNoSelected[0] := Xcol; - ColNoSelected[1] := Ycol; - N := 0; - for i := 1 to NoCases do - begin - if not GoodRecord(i,NoSelected,ColNoSelected) then continue; - X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[Xcol,i])); - Y := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[Ycol,i])); - if X > Xmax then Xmax := X; - if X < Xmin then Xmin := X; - if Y > Ymax then Ymax := Y; - if Y < Ymin then Ymin := Y; - Xmean := Xmean + X; - Ymean := Ymean + Y; - Xvariance := Xvariance + X * X; - Yvariance := Yvariance + Y * Y; - R := R + X * Y; - XYPoints[N,0] := X; - XYPoints[N,1] := Y; - inc(N); - end; - - // sort on X values - for i := 0 to N-2 do - begin - for j := i + 1 to N-1 do - begin - if XYPoints[i,0] > XYPoints[j,0] then // swap - begin - tempX := XYPoints[i,0]; - tempY := XYPoints[i,1]; - XYPoints[i,0] := XYPoints[j,0]; - XYPoints[i,1] := XYPoints[j,1]; - XYPoints[j,0] := tempX; - XYPoints[j,1] := tempY; - end; - end; - end; - - // calculate statistics - Xvariance := Xvariance - Xmean * Xmean / N; - SSx := Xvariance; - Xvariance := Xvariance / (N - 1); - Xstddev := sqrt(Xvariance); - - Yvariance := Yvariance - Ymean * Ymean / N; - Yvariance := Yvariance / (N - 1); - Ystddev := sqrt(Yvariance); - - R := R - (Xmean * Ymean / N); - R := R / (N - 1); - R := R / (Xstddev * Ystddev); - - SEPred := sqrt(1.0 - (R * R)) * Ystddev; - SEPred := SEPred * sqrt((N - 1) / (N - 2)); - - Xmean := Xmean / N; - Ymean := Ymean / N; - Slope := R * Ystddev / Xstddev; - Intercept := Ymean - Slope * Xmean; - - // Now, print the descriptive statistics if requested - lReport := TStringList.Create; - try - if DescChk.Checked then - begin - lReport.Add('Original X versus Y Plot Data'); - lReport.Add(''); - lReport.Add('X = %s, Y = %s from file: %s',[ - Xedit.Text, YEdit.Text, OS3MainFrm.FileNameEdit.Text - ]); - lReport.Add(''); - lReport.Add('Variable Mean Variance Std.Dev.'); - lReport.Add('%-10s%8.2f %8.2f %8.2f', [XEdit.Text, Xmean, Xvariance, Xstddev]); - lReport.Add('%-10s%8.2f %8.2f %8.2f', [YEdit.Text, Ymean, Yvariance, Ystddev]); - lReport.Add(''); - lReport.Add('Correlation: %8.4f', [R]); - lReport.Add('Slope: %8.2f', [Slope]); - lReport.Add('Intercept: %8.2f', [Intercept]); - lReport.Add('Standard Error of Estimate: %8.2f', [SEPred]); - lReport.Add('Number of good cases: %8d', [N]); - lReport.Add(''); - end; - - // get upper and lower confidence points for each X value - if ConfChk.Checked then - begin - ConfBand := StrToFloat(ConfEdit.Text) / 100.0; - DF := N - 2; - t := inverset(ConfBand,DF); - for i := 1 to N do - begin - X := XYpoints[i-1,0]; - predicted := slope * X + intercept; - sedata := SEPred * sqrt(1.0 + (1.0 / N) + (sqr(X - Xmean) / SSx)); - UpConf[i] := predicted + (t * sedata); - lowConf[i] := predicted - (t * sedata); - if UpConf[i] > Ymax then Ymax := UpConf[i]; - if lowConf[i] < Ymin then Ymin := lowConf[i]; - end; - end else - ConfBand := 0.0; - - // plot the values (and optional line and confidence band if elected) - if PointsChk.Checked then - begin - for i := 0 to N-1 do - begin - XVector[i] := XYPoints[i,0]; - YVector[i] := XYPoints[i,1]; - end; - PlotXY( - XVector, YVector, UpConf, LowConf, ConfBand, Xmean, Ymean, R, - Slope, Intercept, Xmax, Xmin, Ymax, Ymin, N, 1 - ); - end; - //LineChk.Checked := false; - //ConfChk.Checked := false; - ConfBand := 0.0; - - // Now do the resistant line analysis - // obtain 1/3 size - size := n div 3; - size1 := size; - size3 := size; - size2 := n - size1 - size3; - GrpSize[0] := size1; - GrpSize[1] := size2; - GrpSize[2] := size3; - - // get median for each group of x and y values - // first group: - for i := 0 to size1-1 do - begin - XVector[i] := XYPoints[i,0]; - YVector[i] := XYPoints[i,1]; - end; - XMedians[0] := Median(XVector,size1); - YMedians[0] := Median(YVector,size1); - - // second group - j := 0; - for i := size1 to size1 + size2 - 1 do - begin - XVector[j] := XYPoints[i,0]; - YVector[j] := XYPoints[i,1]; - inc(j); - end; - XMedians[1] := Median(XVector,size2); - YMedians[1] := Median(YVector,size2); - - // third group - j := 0; - for i := (size1 + size2) to N-1 do - begin - XVector[j] := XYPoints[i,0]; - YVector[j] := XYPoints[i,1]; - inc(j); - end; - XMedians[2] := Median(XVector,size3); - YMedians[2] := Median(YVector,size3); - - lReport.Add('Group X Median Y Median Size'); - for i := 0 to 2 do - lReport.Add('%3d %5.3f %5.3f %d', [i+1, XMedians[i], YMedians[i], GrpSize[i]]); - lReport.Add(''); - - slope1 := (YMedians[1] - YMedians[0]) / (XMedians[1] - XMedians[0]); - slope2 := (YMedians[2] - YMedians[1]) / (XMedians[2] - XMedians[1]); - lReport.Add('Half Slopes: %10.3f and %.3f', [slope1, slope2]); - - Slope := (YMedians[2] - YMedians[0]) / (XMedians[2] - XMedians[0]); - lReport.Add('Slope: %10.3f', [Slope]); - - tempx := slope2 / slope1; - lReport.Add('Ratio of half slopes: %10.3f',[tempx]); - - // obtain estimate of the constant for the prediction equation - c1 := slope * XMedians[0] - YMedians[0]; - c2 := slope * XMedians[1] - YMedians[1]; - c3 := slope * XMedians[2] - YMedians[2]; - c := (c1 + c2 + c3) / 3.0; - lReport.Add('Equation: y := %.3f * X + (%.3f)', [slope, c]); - - if GridChk.Checked then - begin - // Get the residuals (Y - predicted Y) for each X value and place in the grid - outline := 'Pred.' + OS3MainFrm.DataGrid.Cells[Ycol,0]; - DictionaryFrm.NewVar(NoVariables+1); - DictionaryFrm.DictGrid.Cells[1,NoVariables] := outline; - OS3MainFrm.DataGrid.Cells[NoVariables,0] := outline; - - outline := 'Residual'; - DictionaryFrm.NewVar(NoVariables+1); - DictionaryFrm.DictGrid.Cells[1,NoVariables] := outline; - OS3MainFrm.DataGrid.Cells[NoVariables,0] := outline; - - for i := 1 to NoCases do - begin - if not GoodRecord(i,NoSelected,ColNoSelected) then continue; - X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[Xcol,i])); - Y := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[Ycol,i])); - if c >= 0 then - predicted := slope * X + c - else - predicted := slope * X - c; - Y := Y - predicted; // residual - outline := Format('%9.3f',[predicted]); - OS3MainFrm.DataGrid.Cells[NoVariables-1,i] := outline; - outline := Format('%9.3f',[Y]); - OS3MainFrm.DataGrid.Cells[NoVariables,i] := outline; - end; - end; - - DisplayReport(lReport); - - // plot the values (and optional line and confidence band if elected) - if PlotMediansChk.Checked then - PlotXY( - XMedians, YMedians, UpConf, LowConf, ConfBand, Xmean, Ymean, R, - Slope, Intercept, Xmax, Xmin, Ymax, Ymin, 3, 2 - ); - - finally - lReport.Free; - GrpSize := nil; - LowConf := nil; - UpConf := nil; - ColNoSelected := nil; - YVector := nil; - XVector := nil; - YMedians := nil; - XMedians := nil; - XYPoints := nil; - end; + enable := ((Sender = PlotPointsChk) and PlotPointsChk.Checked) or + ((Sender = PlotMediansChk) and (not PlotMediansChk.Checked)); + LineChk.Enabled := enable; + MeansChk.Enabled := enable; + ConfChk.Enabled := enable; + ConfLabel.Enabled := enable; + ConfEdit.Enabled := enable; + GridChk.Enabled := enable; + DescChk.Enabled := enable; end; -procedure TResistanceLineForm.CloseBtnClick(Sender: TObject); -begin - Close; -end; -procedure TResistanceLineForm.FormActivate(Sender: TObject); +procedure TResistanceLineForm.VarListDblClick(Sender: TObject); var - w: Integer; + index: Integer; begin - if FAutoSized then - exit; - - w := MaxValue([ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]); - ResetBtn.Constraints.MinWidth := w; - ComputeBtn.Constraints.MinWidth := w; - CloseBtn.Constraints.MinWidth := w; - - //VarList.Constraints.MinWidth := XEdit.Width; - - Constraints.MinWidth := Width; - Constraints.MinHeight := Height; - - FAutoSized := true; + index := VarList.ItemIndex; + if index > -1 then + begin + if XEdit.Text = '' then + XEdit.Text := VarList.Items[index] + else if YEdit.Text = '' then + YEdit.Text := VarList.Items[index]; + VarList.Items.Delete(index); + UpdateBtnStates; + end; end; -procedure TResistanceLineForm.FormCreate(Sender: TObject); -begin - Assert(OS3MainFrm <> nil); - if BlankFrm = nil then Application.CreateForm(TBlankFrm, BlankFrm); - if DictionaryFrm = nil then Application.CreateForm(TDictionaryFrm, DictionaryFrm); +procedure TResistanceLineForm.UpdateBtnStates; +begin + inherited; + + XInBtn.Enabled := (VarList.ItemIndex > -1) and (XEdit.Text = ''); + YInBtn.Enabled := (VarList.ItemIndex > -1) and (YEdit.Text = ''); + XOutBtn.Enabled := (XEdit.Text <> ''); + YOutBtn.Enabled := (YEdit.Text <> ''); end; + +procedure TResistanceLineForm.VarListSelectionChange(Sender: TObject; + User: boolean); +begin + UpdateBtnStates; +end; + + +procedure TResistanceLineForm.WriteMedianReport(AReport: TStrings; + const XMedians, YMedians: DblDyneVec; const GrpSize: IntDyneVec; + Slope1, Slope2, Slope, Intercept: Double); +var + i: Integer; +begin + AReport.Add('RESISTANT LINE ANALYSIS'); + AReport.Add(''); + AReport.Add('Group X Median Y Median Size'); + AReport.Add('----- -------- -------- -----'); + for i := 0 to 2 do + AReport.Add('%3d %8.3f %8.3f %3d', [i+1, XMedians[i], YMedians[i], GrpSize[i]]); + AReport.Add(''); + + AReport.Add('Half Slopes: %10.3f and %.3f', [Slope1, Slope2]); + AReport.Add('Slope: %10.3f', [Slope]); + aReport.Add('Ratio of half slopes: %10.3f', [Slope2 / Slope1]); + + // Prediction equation + AReport.Add('Equation: y = %.3f * X + %.3f', [Slope, Intercept]); +end; + + +procedure TResistanceLineForm.WriteXYReport(AReport: TStrings; AFileName: String; + xMean, yMean, xVariance, yVariance, xStdDev, yStdDev, R, slope, intercept, SEPred: double; + N: Integer); +begin + AReport.Add(''); + AReport.Add(DIVIDER); + AReport.Add(''); + AReport.Add('ORIGINAL X vs. Y PLOT'); + AReport.Add(''); + AReport.Add('Data file: ' + AFileName); + AReport.Add('Variables:'); + AReport.Add(' X: ' + XEdit.Text); + AReport.Add(' Y: ' + YEdit.Text); +// AReport.Add('X = %s, Y = %s from file: %s', [XEdit.Text, YEdit.Text, AFileName]); + AReport.Add(''); + AReport.Add('Variable Mean Variance Std.Dev.'); + AReport.Add('---------- -------- -------- --------'); + AReport.Add('%-10s %8.2f %8.2f %8.2f', [XEdit.Text, xMean, xVariance, xStdDev]); + AReport.Add('%-10s %8.2f %8.2f %8.2f', [YEdit.Text, yMean, yVariance, yStdDev]); + AReport.Add(''); + AReport.Add('Correlation: %8.4f', [R]); + AReport.Add('Slope: %8.3f', [Slope]); + AReport.Add('Intercept: %8.3f', [Intercept]); + AReport.Add('Standard Error of Estimate: %8.3f', [SEPred]); + AReport.Add('Number of good cases: %8d', [N]); +end; + + procedure TResistanceLineForm.XInBtnClick(Sender: TObject); var index: integer; @@ -432,6 +627,7 @@ begin UpdateBtnStates; end; + procedure TResistanceLineForm.XOutBtnClick(Sender: TObject); begin if XEdit.Text <> '' then @@ -442,6 +638,7 @@ begin UpdateBtnStates; end; + procedure TResistanceLineForm.YInBtnClick(Sender: TObject); var index: integer; @@ -455,6 +652,7 @@ begin UpdateBtnStates; end; + procedure TResistanceLineForm.YOutBtnClick(Sender: TObject); begin if YEdit.Text <> '' then @@ -465,286 +663,6 @@ begin UpdateBtnStates; end; -function TResistanceLineForm.Median(VAR X: DblDyneVec; ASize: integer): double; -var - midpt: integer; - value: double; - i, j: integer; -begin - // sort values - for i := 0 to ASize-2 do - begin - for j := i + 1 to ASize-1 do - begin - if X[i] > X[j] then // swap - begin - value := X[i]; - X[i] := X[j]; - X[j] := value; - end; - end; - end; - - if ASize > 2 then - begin - midpt := ASize div 2; - if 2 * midpt = ASize then // even no. of values - begin - value := (X[midpt-1] + X[midpt]) / 2; - end else - value := X[midpt]; // odd no. of values - Median := value; - end else - if ASize = 2 then - Median := (X[0] + X[1]) / 2; - - Result := Median; -end; - -procedure TResistanceLineForm.PlotXY(const Xpoints, Ypoints, UpConf, LowConf: DblDyneVec; - ConfBand, XMean, YMean, R, Slope, Intercept: double; - Xmax, Xmin, Ymax, Ymin: double; N, PlotNo: integer); -var - i, xpos, ypos, hleft, hright, vtop, vbottom, imagewide: integer; - vhi, hwide, offset, strhi, imagehi: integer; - valincr, Yvalue, Xvalue: double; - Title: string; - YU, YL, XU, XL: double; -begin - BlankFrm.Image1.Canvas.Clear; - if PlotNo = 1 then - begin - Title := 'X versus Y PLOT Using File: ' + OS3MainFrm.FileNameEdit.Text; - BlankFrm.Caption := Title; - end - else - begin - Title := 'Median Plot for three groups'; - BlankFrm.Caption := Title; - end; - imagewide := BlankFrm.Image1.Width; - imagehi := BlankFrm.Image1.Height; - vtop := 40; - vbottom := round(imagehi) - 80; - vhi := vbottom - vtop; - hleft := 100; - hright := imagewide - 80; - hwide := hright - hleft; - BlankFrm.Image1.Canvas.Pen.Color := clBlack; - BlankFrm.Image1.Canvas.Brush.Color := clWhite; - - // Draw chart border - BlankFrm.Image1.Canvas.Rectangle(0,0,imagewide,imagehi); - - // draw Means - if MeansChk.Checked then - begin - ypos := round(vhi * ( (Ymax - Ymean) / (Ymax - Ymin))); - ypos := ypos + vtop; - xpos := hleft; - BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); - xpos := hright; - BlankFrm.Image1.Canvas.Pen.Color := clGreen; - BlankFrm.Image1.Canvas.LineTo(xpos,ypos); - Title := 'MEAN '; - Title := Title + YEdit.Text; - strhi := BlankFrm.Image1.Canvas.TextHeight(Title); - ypos := ypos - strhi div 2; - BlankFrm.Image1.Canvas.Brush.Color := clWhite; - BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title); - - xpos := round(hwide * ( (Xmean - Xmin) / (Xmax - Xmin))); - xpos := xpos + hleft; - ypos := vtop; - BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); - ypos := vbottom; - BlankFrm.Image1.Canvas.Pen.Color := clGreen; - BlankFrm.Image1.Canvas.LineTo(xpos,ypos); - Title := 'MEAN '; - Title := Title + XEdit.Text; - strhi := BlankFrm.Image1.Canvas.TextWidth(Title); - xpos := xpos - strhi div 2; - ypos := vtop - BlankFrm.Image1.Canvas.TextHeight(Title); - BlankFrm.Image1.Canvas.Brush.Color := clWhite; - BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title); - end; - - // draw slope line - if LineChk.Checked then - begin - BlankFrm.Image1.Canvas.Pen.Color := clBlack; - Yvalue := (Xpoints[0] * slope) + intercept; // predicted score - ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin))); - ypos := ypos + vtop; - xpos := round(hwide * ( (Xpoints[0]- Xmin) / (Xmax - Xmin))); - xpos := xpos + hleft; - BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); - Yvalue := (Xpoints[N-1] * slope) + intercept; // predicted score - ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin))); - ypos := ypos + vtop; - xpos := round(hwide * ( (Xpoints[N-1] - Xmin) / (Xmax - Xmin))); - xpos := xpos + hleft; - BlankFrm.Image1.Canvas.LineTo(xpos,ypos); - end; - - // draw horizontal axis - BlankFrm.Image1.Canvas.Pen.Color := clBlack; - BlankFrm.Image1.Canvas.MoveTo(hleft,vbottom); - BlankFrm.Image1.Canvas.LineTo(hright,vbottom); - valincr := (Xmax - Xmin) / 10.0; - for i := 1 to 11 do - begin - ypos := vbottom; - Xvalue := Xmin + valincr * (i - 1); - xpos := round(hwide * ((Xvalue - Xmin) / (Xmax - Xmin))); - xpos := xpos + hleft; - BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); - ypos := ypos + 10; - BlankFrm.Image1.Canvas.LineTo(xpos,ypos); - Title := format('%.2f',[Xvalue]); - offset := BlankFrm.Image1.Canvas.TextWidth(Title) div 2; - xpos := xpos - offset; - BlankFrm.Image1.Canvas.Pen.Color := clBlack; - BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title); - end; - if PlotNo = 1 then - begin - xpos := hleft + (hwide div 2) - (BlankFrm.Image1.Canvas.TextWidth(XEdit.Text) div 2); - ypos := vbottom + 20; - BlankFrm.Image1.Canvas.TextOut(xpos,ypos,XEdit.Text); - Title := format('R(X,Y) = %.3f, Slope = %.2f, Intercept = %.2f', - [R,Slope,Intercept]); - xpos := hleft + (hwide div 2) - (BlankFrm.Image1.Canvas.TextWidth(Title) div 2); - ypos := ypos + 15; - BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title); - end; - - // Draw vertical axis - Title := YEdit.Text; - xpos := hleft - BlankFrm.Image1.Canvas.TextWidth(Title) div 2; - ypos := vtop - BlankFrm.Image1.Canvas.TextHeight(Title) - 10; - BlankFrm.Image1.Canvas.TextOut(xpos,ypos,YEdit.Text); - xpos := hleft; - ypos := vtop; - BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); - ypos := vbottom; - BlankFrm.Image1.Canvas.LineTo(xpos,ypos); - valincr := (Ymax - Ymin) / 10.0; - for i := 1 to 11 do - begin - Title := format('%.2f',[Ymax - ((i-1)*valincr)]); - strhi := BlankFrm.Image1.Canvas.TextHeight(Title); - xpos := hLeft - 20 - BlankFrm.Image1.Canvas.TextWidth(Title); //10; - Yvalue := Ymax - (valincr * (i-1)); - ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin))); - ypos := ypos + vtop - strhi div 2; - BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title); - xpos := hleft; - ypos := ypos + strhi div 2; - BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); - xpos := hleft - 10; - BlankFrm.Image1.Canvas.LineTo(xpos,ypos); - end; - - // draw points for x and y pairs - for i := 0 to N-1 do - begin - ypos := round(vhi * ( (Ymax - Ypoints[i]) / (Ymax - Ymin))); - ypos := ypos + vtop; - xpos := round(hwide * ( (Xpoints[i] - Xmin) / (Xmax - Xmin))); - xpos := xpos + hleft; - BlankFrm.Image1.Canvas.Brush.Color := clYellow; - BlankFrm.Image1.Canvas.Brush.Style := bsSolid; - BlankFrm.Image1.Canvas.Pen.Color := clNavy; - BlankFrm.Image1.Canvas.Ellipse(xpos,ypos,xpos+5,ypos+5); - if ((PlotNo = 2) and (i = 0)) then - begin - BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); - BlankFrm.Image1.Canvas.TextOut(xpos,ypos,'M1'); - end; - if ((PlotNo = 2) and (i > 0)) then - begin - BlankFrm.Image1.Canvas.LineTo(xpos,ypos); - Title := format('M%d',[i+1]); - BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title); - end; - end; - if ((PlotNo = 2) and (i > 0)) then - begin // draw slope line - BlankFrm.Image1.Canvas.Pen.Color := clRed; - ypos := round(vhi * ( (Ymax - Ypoints[0]) / (Ymax - Ymin))); - ypos := ypos + vtop; - xpos := round(hwide * ( (Xpoints[0] - Xmin) / (Xmax - Xmin))); - xpos := xpos + hleft; - BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); - YL := Ypoints[0]; - XL := xpoints[0]; - ypos := round(vhi * ( (Ymax - Ypoints[2]) / (Ymax - Ymin))); - ypos := ypos + vtop; - xpos := round(hwide * ( (Xpoints[2] - Xmin) / (Xmax - Xmin))); - xpos := xpos + hleft; - BlankFrm.Image1.Canvas.LineTo(xpos,ypos); - YU := Ypoints[2]; - XU := xpoints[2]; - slope := (YU - YL) / (XU - XL); - ypos := vbottom + 20; - BlankFrm.Image1.Canvas.Brush.Color := clYellow; - Title := format('Slope = %.2f',[Slope]); - xpos := hleft + (hwide div 2) - (BlankFrm.Image1.Canvas.TextWidth(Title) div 2); - ypos := ypos + 15; - BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title); - end; - - // draw confidence bands if requested - if ConfBand <> 0.0 then - begin - BlankFrm.Image1.Canvas.Pen.Color := clRed; - ypos := round(vhi * ((Ymax - UpConf[1]) / (Ymax - Ymin))); - ypos := ypos + vtop; - xpos := round(hwide * ( (Xpoints[0] - Xmin) / (Xmax - Xmin))); - xpos := xpos + hleft; - BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); - for i := 2 to N do - begin - ypos := round(vhi * ((Ymax - UpConf[i]) / (Ymax - Ymin))); - ypos := ypos + vtop; - xpos := round(hwide * ( (Xpoints[i-1] - Xmin) / (Xmax - Xmin))); - xpos := xpos + hleft; - BlankFrm.Image1.Canvas.LineTo(xpos,ypos); - end; - ypos := round(vhi * ((Ymax - lowConf[1]) / (Ymax - Ymin))); - ypos := ypos + vtop; - xpos := round(hwide * ( (Xpoints[0] - Xmin) / (Xmax - Xmin))); - xpos := xpos + hleft; - BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); - for i := 2 to N do - begin - ypos := round(vhi * ((Ymax - lowConf[i]) / (Ymax - Ymin))); - ypos := ypos + vtop; - xpos := round(hwide * ( (Xpoints[i-1] - Xmin) / (Xmax - Xmin))); - xpos := xpos + hleft; - BlankFrm.Image1.Canvas.LineTo(xpos,ypos); - end; - end; - BlankFrm.ShowModal; -end; - -procedure TResistanceLineForm.UpdateBtnStates; -begin - XInBtn.Enabled := (VarList.ItemIndex > -1) and (XEdit.Text = ''); - YInBtn.Enabled := (VarList.ItemIndex > -1) and (YEdit.Text = ''); - XOutBtn.Enabled := (XEdit.Text <> ''); - YOutBtn.Enabled := (YEdit.Text <> ''); -end; - -procedure TResistanceLineForm.VarListSelectionChange(Sender: TObject; - User: boolean); -begin - UpdateBtnStates; -end; - -initialization - {$I resistancelineunit.lrs} end. diff --git a/applications/lazstats/source/forms/simulations/distribunit.lfm b/applications/lazstats/source/forms/simulations/distribunit.lfm index 0c6d05ff1..7a525102c 100644 --- a/applications/lazstats/source/forms/simulations/distribunit.lfm +++ b/applications/lazstats/source/forms/simulations/distribunit.lfm @@ -21,17 +21,17 @@ inherited DistribFrm: TDistribFrm TabOrder = 6 end inherited ComputeBtn: TButton - Left = 70 + Left = 69 Top = 387 TabOrder = 5 end inherited ResetBtn: TButton - Left = 8 + Left = 7 Top = 387 TabOrder = 4 end inherited HelpBtn: TButton - Left = -51 + Left = -52 Top = 387 Visible = False end diff --git a/applications/lazstats/source/forms/simulations/distribunit.pas b/applications/lazstats/source/forms/simulations/distribunit.pas index cd4a3cd12..4db133183 100644 --- a/applications/lazstats/source/forms/simulations/distribunit.pas +++ b/applications/lazstats/source/forms/simulations/distribunit.pas @@ -95,7 +95,6 @@ begin FChartFrame.Chart.Legend.ColumnCount := 3; FChartFrame.Chart.Legend.TextFormat := tfHTML; -// InitToolbar(FChartFrame.ChartToolbar, tpTop); tbErase := TToolButton.Create(self); tbErase.ImageIndex := 6; tbErase.Caption := 'Erase'; diff --git a/applications/lazstats/source/units/gridprocs.pas b/applications/lazstats/source/units/gridprocs.pas index e921af1b1..b4b923843 100644 --- a/applications/lazstats/source/units/gridprocs.pas +++ b/applications/lazstats/source/units/gridprocs.pas @@ -14,6 +14,8 @@ function CollectValues(AGrid: TStringGrid; AColIndex: Integer; procedure GetMinMax(AGrid: TStringGrid; AColIndex: Integer; const AColCheck: IntDyneVec; out AMin, AMax: Double); +function GetVariableIndex(AGrid: TStringGrid; const AVarName: String): Integer; + function GoodRecord(AGrid: TStringGrid; ARow: integer; const AColCheck: IntDyneVec): boolean; @@ -93,6 +95,14 @@ begin end; +{ Finds the index of the variable with the specified name among the columns of + the grid. } +function GetVariableIndex(AGrid: TStringGrid; const AVarName: String): Integer; +begin + Result := AGrid.Rows[0].IndexOf(AVarName); +end; + + { Checks whether all cells specified for the given row in the columns listed in the GridPos array are "valid": not filtered and not empty } function GoodRecord(AGrid: TStringGrid; ARow: integer; diff --git a/applications/lazstats/source/units/mathunit.pas b/applications/lazstats/source/units/mathunit.pas index 78895d988..513fbb16a 100644 --- a/applications/lazstats/source/units/mathunit.pas +++ b/applications/lazstats/source/units/mathunit.pas @@ -51,11 +51,14 @@ procedure Calc_MeanVarStdDev(const AData: DblDyneVec; out AMean, AVariance, AStd procedure Calc_MeanVarStdDevSS(const AData: DblDyneVec; out AMean, AVariance, AStdDev, ASumOfSquares: Double); procedure Calc_SumSS(const AData: DblDyneVec; out Sum, SS: Double); +function Calc_Median(const AData: DblDyneVec): Double; + implementation uses - Math; + Math, + Utils; // Calculates the error function // /x @@ -572,6 +575,21 @@ begin end; +function Calc_Median(const AData: DblDyneVec): Double; +var + N, midPt: integer; +begin + SortOnX(AData); + + N := Length(AData); + midPt := N div 2; + if odd(N) then + Result := AData[midPt] // odd no. of values + else + Result := (AData[midPt-1] + AData[midPt]) / 2; // even no. of values +end; + + initialization InitFactLn();