You've already forked lazarus-ccr
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7881 8e941d3f-bd1b-0410-a28a-d453659cc2b4
371 lines
12 KiB
ObjectPascal
371 lines
12 KiB
ObjectPascal
unit CorSimUnit;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
|
|
ExtCtrls, StdCtrls, Globals, OutPutUnit, Math;
|
|
|
|
type
|
|
|
|
{ TCorSimFrm }
|
|
|
|
TCorSimFrm = class(TForm)
|
|
Nobs: TEdit;
|
|
Image1: TImage;
|
|
Label6: TLabel;
|
|
ReturnBtn: TButton;
|
|
ComputeBtn: TButton;
|
|
Corr: TEdit;
|
|
Label5: TLabel;
|
|
SDY: TEdit;
|
|
Label4: TLabel;
|
|
SDX: TEdit;
|
|
Label3: TLabel;
|
|
MeanY: TEdit;
|
|
Label2: TLabel;
|
|
MeanX: TEdit;
|
|
Label1: TLabel;
|
|
Panel1: TPanel;
|
|
procedure ComputeBtnClick(Sender: TObject);
|
|
procedure CorrKeyPress(Sender: TObject; var Key: char);
|
|
procedure FormShow(Sender: TObject);
|
|
procedure MeanXKeyPress(Sender: TObject; var Key: char);
|
|
procedure MeanYKeyPress(Sender: TObject; var Key: char);
|
|
procedure NobsKeyPress(Sender: TObject; var Key: char);
|
|
procedure SDXKeyPress(Sender: TObject; var Key: char);
|
|
procedure SDYKeyPress(Sender: TObject; var Key: char);
|
|
private
|
|
{ private declarations }
|
|
xmean, ymean, xsd, ysd, corxy, corsqr, yvariance, predvar : double;
|
|
errvariance, stderror, b, constant, newxmean, newymean : double;
|
|
newxsd, newysd, newcorr, randomerror, newb, newconstant : double;
|
|
x, y : DblDyneVec;
|
|
freqx, freqy : IntDyneVec;
|
|
N : integer;
|
|
procedure plot(Sender: TObject);
|
|
public
|
|
{ public declarations }
|
|
end;
|
|
|
|
var
|
|
CorSimFrm: TCorSimFrm;
|
|
|
|
implementation
|
|
|
|
{ TCorSimFrm }
|
|
|
|
procedure TCorSimFrm.MeanXKeyPress(Sender: TObject; var Key: char);
|
|
begin
|
|
if Ord(Key) = 13 then MeanY.SetFocus;
|
|
end;
|
|
|
|
procedure TCorSimFrm.CorrKeyPress(Sender: TObject; var Key: char);
|
|
begin
|
|
if Ord(Key) = 13 then Nobs.SetFocus;
|
|
end;
|
|
|
|
procedure TCorSimFrm.ComputeBtnClick(Sender: TObject);
|
|
var
|
|
outline : string;
|
|
i : integer;
|
|
begin
|
|
N := StrToInt(NObs.Text);
|
|
xmean := StrToFloat(MeanX.Text);
|
|
ymean := StrToFloat(MeanY.Text);
|
|
xsd := StrToFloat(SDX.Text);
|
|
ysd := StrToFloat(SDY.Text);
|
|
corxy := StrToFloat(Corr.Text);
|
|
Randomize;
|
|
|
|
SetLength(freqx,N + 1);
|
|
SetLength(freqy,N + 1);
|
|
SetLength(x,N + 1);
|
|
SetLength(y,N + 1);
|
|
|
|
// generate x and y data observations
|
|
corsqr := corxy * corxy;
|
|
yvariance := ysd * ysd;
|
|
predvar := corsqr * yvariance;
|
|
errvariance := yvariance - predvar;
|
|
stderror := sqrt(errvariance);
|
|
b := corxy * (ysd / xsd);
|
|
constant := ymean - (b * xmean);
|
|
|
|
newxmean := 0.0;
|
|
newymean := 0.0;
|
|
newxsd := 0.0;
|
|
newysd := 0.0;
|
|
newcorr := 0.0;
|
|
for i := 1 to N do
|
|
begin
|
|
x[i] := RandG(xmean,xsd);
|
|
randomerror := RandG(0.0,stderror);
|
|
y[i] := (b * x[i]) + constant + randomerror;
|
|
newxmean := newxmean + x[i];
|
|
newymean := newymean + y[i];
|
|
newxsd := newxsd + (x[i] * x[i]);
|
|
newysd := newysd + (y[i] * y[i]);
|
|
newcorr := newcorr + (x[i] * y[i]);
|
|
end;
|
|
newxsd := newxsd - ((newxmean * newxmean) / N);
|
|
newxsd := newxsd / (N - 1.0);
|
|
newxsd := sqrt(newxsd);
|
|
newysd := newysd - ((newymean * newymean) / N);
|
|
newysd := newysd / (N - 1.0);
|
|
newysd := sqrt(newysd);
|
|
newcorr := newcorr - ((newxmean * newymean) / N);
|
|
newcorr := newcorr / (N - 1.0);
|
|
newcorr := newcorr / (newxsd * newysd);
|
|
newxmean := newxmean / N;
|
|
newymean := newymean / N;
|
|
newb := newcorr * (newysd / newxsd);
|
|
newconstant := newymean - (newb * newxmean);
|
|
OutPutFrm.RichEdit.Lines.Clear;
|
|
outline := 'POPULATION PARAMETERS FOR THE SIMULATION';
|
|
OutPutFrm.RichEdit.Lines.Add(outline);
|
|
OutPutFrm.RichEdit.Lines.Add('');
|
|
outline := format('Mean X := %8.3f, Std. Dev. X := %8.3f',[xmean, xsd]);
|
|
OutPutFrm.RichEdit.Lines.Add(outline);
|
|
outline := format('Mean Y := %8.3f, Std. Dev. Y := %8.3f',[ymean, ysd]);
|
|
OutPutFrm.RichEdit.Lines.Add(outline);
|
|
outline := format('Product-Moment Correlation := %8.3f',[corxy]);
|
|
OutPutFrm.RichEdit.Lines.Add(outline);
|
|
outline := format('Regression line slope := %8.3f, constant := %8.3f',
|
|
[b, constant]);
|
|
OutPutFrm.RichEdit.Lines.Add(outline);
|
|
OutPutFrm.RichEdit.Lines.Add('');
|
|
OutPutFrm.RichEdit.Lines.Add('');
|
|
outline := format('SAMPLE STATISTICS FOR %d OBSERVATIONS FROM THE POPULATION',[N]);
|
|
OutPutFrm.RichEdit.Lines.Add(outline);
|
|
OutPutFrm.RichEdit.Lines.Add('');
|
|
outline := format('Mean X := %8.3f, Std. Dev. X := %8.3f',[newxmean, newxsd]);
|
|
OutPutFrm.RichEdit.Lines.Add(outline);
|
|
outline := format('Mean Y := %8.3f, Std. Dev. Y := %8.3f',[newymean, newysd]);
|
|
OutPutFrm.RichEdit.Lines.Add(outline);
|
|
outline := format('Product-Moment Correlation := %8.3f',[newcorr]);
|
|
OutPutFrm.RichEdit.Lines.Add(outline);
|
|
outline := format('Regression line slope := %8.3f, constant := %8.3f',
|
|
[newb, newconstant]);
|
|
OutPutFrm.RichEdit.Lines.Add(outline);
|
|
OutPutFrm.RichEdit.Lines.Add('');
|
|
OutPutFrm.RichEdit.Lines.Add('Pair No. X Y');
|
|
for i := 1 to N do
|
|
begin
|
|
outline := format(' %3d %9.3f %9.3f',[i,x[i],y[i]]);
|
|
OutPutFrm.RichEdit.Lines.Add(outline);
|
|
end;
|
|
OutPutFrm.ShowModal;
|
|
plot(self);
|
|
freqx := nil;
|
|
freqy := nil;
|
|
x := nil;
|
|
y := nil;
|
|
ReturnBtn.SetFocus;
|
|
end;
|
|
|
|
procedure TCorSimFrm.FormShow(Sender: TObject);
|
|
begin
|
|
CorSimFrm.Image1.Canvas.Pen.Color := clBlack;
|
|
CorSimFrm.Image1.Canvas.Brush.Color := clWhite;
|
|
CorSimFrm.Image1.Canvas.Clear;
|
|
CorSimFrm.Image1.Canvas.FloodFill(1,1,clWhite,fsborder);
|
|
MeanX.Text := '100';
|
|
MeanY.Text := '100';
|
|
SDX.Text := '15';
|
|
SDY.Text := '15';
|
|
Corr.Text := '.8';
|
|
Nobs.Text := '100';
|
|
end;
|
|
|
|
procedure TCorSimFrm.MeanYKeyPress(Sender: TObject; var Key: char);
|
|
begin
|
|
if Ord(Key) = 13 then SDX.SetFocus;
|
|
end;
|
|
|
|
procedure TCorSimFrm.NobsKeyPress(Sender: TObject; var Key: char);
|
|
begin
|
|
if Ord(Key) = 13 then ComputeBtn.SetFocus;
|
|
end;
|
|
|
|
procedure TCorSimFrm.SDXKeyPress(Sender: TObject; var Key: char);
|
|
begin
|
|
if Ord(Key) = 13 then SDY.SetFocus;
|
|
end;
|
|
|
|
procedure TCorSimFrm.SDYKeyPress(Sender: TObject; var Key: char);
|
|
begin
|
|
if Ord(Key) = 13 then Corr.SetFocus;
|
|
end;
|
|
|
|
procedure TCorSimFrm.plot(Sender: TObject);
|
|
var
|
|
minx, maxx, miny, maxy, xincrement, yincrement : double;
|
|
predy1, predy2, lowerx, upperx, frange, prop : double;
|
|
charlabel : string;
|
|
xpos, ypos, xpos1, ypos1, xpos2, ypos2 : integer;
|
|
i, winwidth, winheight, xoffset, yoffset, xaxislong, yaxislong : integer;
|
|
j, xspacing, yspacing, labelwidth, minfreq, maxfreq : integer;
|
|
flength, theight, lowery, uppery : integer;
|
|
begin
|
|
// get min and max of x and y points
|
|
minx := x[1];
|
|
maxx := minx;
|
|
miny := y[1];
|
|
maxy := miny;
|
|
for i := 1 to N do
|
|
begin
|
|
if (minx > x[i]) then minx := x[i];
|
|
if (maxx < x[i]) then maxx := x[i];
|
|
if (miny > y[i]) then miny := y[i];
|
|
if (maxy < y[i]) then maxy := y[i];
|
|
end;
|
|
xincrement := (maxx - minx) / 10;
|
|
yincrement := (maxy - miny) / 10;
|
|
|
|
winwidth := CorSimFrm.Image1.Width;
|
|
winheight := CorSimFrm.Image1.Height;
|
|
xoffset := winwidth div 5;
|
|
yoffset := winheight div 5;
|
|
xaxislong := winwidth - xoffset- winwidth div 10;
|
|
yaxislong := winheight - yoffset - winheight div 10;
|
|
Image1.Canvas.Pen.Color := clBlack;
|
|
Image1.Canvas.MoveTo(xoffset,yaxislong);
|
|
Image1.Canvas.LineTo(winwidth,yaxislong);
|
|
Image1.Canvas.MoveTo(xoffset,yaxislong);
|
|
Image1.Canvas.LineTo(xoffset,0);
|
|
xspacing := xaxislong div 10;
|
|
yspacing := yaxislong div 10;
|
|
// do xaxis
|
|
for i := 0 to 11 do
|
|
begin
|
|
Image1.Canvas.MoveTo(xoffset + (i * xspacing),yaxislong);
|
|
Image1.Canvas.LineTo(xoffset + (i * xspacing),yaxislong + 10);
|
|
charlabel := format('%8.3f',[minx + (i * xincrement)]);
|
|
labelwidth := Image1.Canvas.TextWidth(charlabel);
|
|
xpos := xoffset + (i * xspacing)-labelwidth div 2;
|
|
ypos := yaxislong + 12;
|
|
Image1.Canvas.TextOut(xpos,ypos,charlabel);
|
|
end;
|
|
// do yaxis
|
|
for i := 0 to 11 do
|
|
begin
|
|
Image1.Canvas.MoveTo(xoffset, yaxislong - (i * yspacing));
|
|
Image1.Canvas.LineTo(xoffset-10,yaxislong - (i * yspacing));
|
|
charlabel := format('%8.3f',[miny + (i * yincrement)]);
|
|
labelwidth := Image1.Canvas.TextWidth(charlabel);
|
|
xpos := xoffset-10-labelwidth;
|
|
ypos := yaxislong - (i * yspacing);
|
|
Image1.Canvas.TextOut(xpos,ypos,charlabel);
|
|
end;
|
|
// plot points
|
|
Image1.Canvas.Pen.Color := clRed;
|
|
for i := 1 to N do
|
|
begin
|
|
xpos := round(xoffset + ((x[i] - minx) / (maxx - minx) * xaxislong));
|
|
ypos := round(yaxislong - ((y[i] - miny) / (maxy - miny) * yaxislong));
|
|
Image1.Canvas.Ellipse(xpos,ypos,xpos+5,ypos+5);
|
|
end;
|
|
// draw regression line
|
|
Image1.Canvas.Pen.Color := clBlack;
|
|
predy1 := newb * minx + newconstant;
|
|
predy2 := newb * maxx + newconstant;
|
|
xpos1 := xoffset;
|
|
xpos2 := xoffset + xaxislong;
|
|
ypos1 := round(yaxislong - ((predy1 - miny) / (maxy - miny) * yaxislong));
|
|
ypos2 := round(yaxislong - ((predy2 - miny) / (maxy - miny) * yaxislong));
|
|
Image1.Canvas.MoveTo(xpos1,ypos1);
|
|
Image1.Canvas.LineTo(xpos2,ypos2);
|
|
|
|
// do x frequency distribution
|
|
xincrement := (maxx-minx) / 50.0;
|
|
xspacing := xaxislong div 50;
|
|
for j := 1 to 51 do freqx[j] := 0;
|
|
for i := 1 to N do
|
|
begin
|
|
for j := 1 to 51 do
|
|
begin
|
|
lowerx := minx + (j * xincrement);
|
|
upperx := minx + ((j+1) * xincrement);
|
|
if ((x[i] >= lowerx) and (x[i] < upperx)) then freqx[j] := freqx[j] + 1;
|
|
end;
|
|
end;
|
|
// plot the x frequencies
|
|
minfreq := N;
|
|
maxfreq := 0;
|
|
for j := 1 to 51 do
|
|
begin
|
|
if (freqx[j] > maxfreq) then maxfreq := freqx[j];
|
|
if (freqx[j] < minfreq) then minfreq := freqx[j];
|
|
end;
|
|
flength := winheight - (yaxislong + 25) - Panel1.Height;
|
|
for j := 1 to 51 do
|
|
begin
|
|
xpos := xoffset + (j * xspacing);
|
|
ypos1 := round(yaxislong + 25 +
|
|
((freqx[j] - minfreq)/ (maxfreq-minfreq) * (flength)));
|
|
ypos2 := yaxislong + 25;
|
|
Image1.Canvas.MoveTo(xpos,ypos1);
|
|
Image1.Canvas.LineTo(xpos,ypos2);
|
|
end;
|
|
Image1.Canvas.MoveTo(xoffset,yaxislong+25);
|
|
Image1.Canvas.LineTo(winwidth,yaxislong+25);
|
|
xpos := 20;
|
|
ypos := yaxislong+30;
|
|
Image1.Canvas.TextOut(xpos,ypos,'X DISTRIBUTION');
|
|
theight := Image1.Canvas.TextHeight('X');
|
|
ypos := ypos + theight;
|
|
charlabel := format('correlation := %6.3f',[newcorr]);
|
|
Image1.Canvas.TextOut(xpos,ypos,charlabel);
|
|
ypos := ypos + theight;
|
|
charlabel := format('Mean X := %8.3f, Mean Y := %8.3f',[newxmean, newymean]);
|
|
Image1.Canvas.TextOut(xpos,ypos,charlabel);
|
|
charlabel := format('SD X := %8.3f, SD Y := %8.3f',[newxsd, newysd]);
|
|
ypos := ypos + theight;
|
|
Image1.Canvas.TextOut(xpos,ypos,charlabel);
|
|
|
|
// do y frequency distribution
|
|
yincrement := (maxy-miny) / 50.0;
|
|
yspacing := yaxislong div 50;
|
|
for j := 1 to 51 do freqy[j] := 0;
|
|
for i := 1 to N do
|
|
begin
|
|
for j := 1 to 51 do
|
|
begin
|
|
lowery := round(miny + (j * yincrement));
|
|
uppery := round(miny + ((j+1) * yincrement));
|
|
if ((y[i] >= lowery) and (y[i] < uppery)) then freqy[j] := freqy[j] + 1;
|
|
end;
|
|
end;
|
|
// plot the y frequencies
|
|
minfreq := N;
|
|
maxfreq := 0;
|
|
for j := 1 to 51 do
|
|
begin
|
|
if (freqy[j] > maxfreq) then maxfreq := freqy[j];
|
|
if (freqy[j] < minfreq) then minfreq := freqy[j];
|
|
end;
|
|
flength := winwidth - (xaxislong + 150);
|
|
for j := 1 to 51 do
|
|
begin
|
|
ypos := yaxislong - (j * yspacing);
|
|
frange := maxfreq - minfreq;
|
|
prop := (freqy[j] - minfreq) / frange;
|
|
xpos1 := round(xoffset - 50 - (prop * flength));
|
|
xpos2 := xoffset - 50;
|
|
Image1.Canvas.MoveTo(xpos1,ypos);
|
|
Image1.Canvas.LineTo(xpos2,ypos);
|
|
end;
|
|
Image1.Canvas.MoveTo(xoffset - 50,yaxislong);
|
|
Image1.Canvas.LineTo(xoffset - 50,0);
|
|
Image1.Canvas.TextOut(0,0,'Y DISTRIBUTION');
|
|
end;
|
|
|
|
initialization
|
|
{$I corsimunit.lrs}
|
|
|
|
end.
|
|
|