Files
lazarus-ccr/applications/lazstats/source/forms/analysis/descriptive/xvsmultyunit.pas

457 lines
12 KiB
ObjectPascal
Raw Normal View History

// Use file "SchoolsData.laz" for testing
unit XvsMultYUnit;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
StdCtrls, Buttons, ExtCtrls, Printers,
MainUnit, Globals, OutputUnit, DataProcs, BlankFrmUnit, MatrixLib;
type
{ TXvsMultYForm }
TXvsMultYForm = class(TForm)
Bevel1: TBevel;
Bevel2: TBevel;
LinesBox: TCheckBox;
DescChk: TCheckBox;
GroupBox1: TGroupBox;
Memo1: TLabel;
Panel1: TPanel;
ResetBtn: TButton;
ComputeBtn: TButton;
CloseBtn: TButton;
PlotTitleEdit: TEdit;
Label4: TLabel;
YBox: TListBox;
XEdit: TEdit;
Label2: TLabel;
Label3: TLabel;
XInBtn: TBitBtn;
YInBtn: TBitBtn;
Label1: TLabel;
XOutBtn: TBitBtn;
YOutBtn: TBitBtn;
VarList: TListBox;
procedure ComputeBtnClick(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ResetBtnClick(Sender: TObject);
procedure VarListSelectionChange(Sender: TObject; User: boolean);
procedure XInBtnClick(Sender: TObject);
procedure XOutBtnClick(Sender: TObject);
procedure YInBtnClick(Sender: TObject);
procedure YOutBtnClick(Sender: TObject);
private
{ private declarations }
FAutoSized: Boolean;
selected: IntDyneVec;
procedure PlotXY(XValues : DblDyneVec; YValues : DblDyneMat; MaxX, MinX,
MaxY, MinY : double; N, NoY : integer);
procedure UpdateBtnStates;
public
{ public declarations }
end;
var
XvsMultYForm: TXvsMultYForm;
implementation
uses
Math, Utils;
{ TXvsMultYForm }
procedure TXvsMultYForm.ResetBtnClick(Sender: TObject);
VAR i : integer;
begin
VarList.Clear;
YBox.Clear;
XEdit.Clear;
XInBtn.Enabled := true;
XOutBtn.Enabled := false;
YInBtn.Enabled := true;
YOutBtn.Enabled := false;
PlotTitleEdit.Text := '';
for i := 1 to NoVariables do
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
end;
procedure TXvsMultYForm.VarListSelectionChange(Sender: TObject; User: boolean);
begin
UpdateBtnStates;
end;
procedure TXvsMultYForm.ComputeBtnClick(Sender: TObject);
var
i, j, k, N, NoY, XCol, NoSelected: integer;
YValues, RMatrix: DblDyneMat;
XValues, Means, Variances, StdDevs: DblDyneVec;
MinX, MaxX, MinY, MaxY, temp: double;
Title: string;
RowLabels, ColLabels: StrDyneVec;
lReport: TStrings;
errorcode: boolean = false;
Ncases: integer = 0;
begin
if XEdit.Text = '' then
begin
MessageDlg('No X variable selected.', mtError, [mbOK], 0);
exit;
end;
if YBox.Items.Count = 0 then
begin
MessageDlg('No Y variables selected.', mtError, [mbOK], 0);
exit;
end;
NoY := YBox.Items.Count;
MaxX := -10000;
MinX := 10000;
MaxY := -1000;
MinY := 1000;
N := 0;
SetLength(selected, NoY + 1);
SetLength(RowLabels,NoVariables);
SetLength(ColLabels,NoVariables);
XCol := 0;
for i := 1 to NoVariables do
if Trim(XEdit.Text) = Trim(OS3MainFrm.DataGrid.Cells[i,0]) then
begin
XCol := i;
break;
end;
for j := 0 to NoY-1 do
begin
selected[j] := 0;
for i := 1 to NoVariables do
if Trim(YBox.Items.Strings[j]) = Trim(OS3MainFrm.DataGrid.Cells[i,0]) then
begin
selected[j] := i;
Break;
end;
end;
selected[NoY] := XCol;
NoSelected := NoY + 1;
for i := 0 to NoSelected-1 do
begin
RowLabels[i] := Trim(OS3MainFrm.DataGrid.Cells[selected[i],0]);
ColLabels[i] := RowLabels[i];
end;
Caption := RowLabels[0] + ' ' + RowLabels[1];
lReport := TStringList.Create;
try
lReport.Add('X VERSUS MULTIPLE Y VALUES PLOT');
lReport.Add('');
SetLength(YValues, NoCases+1, NoY+1);
SetLength(XValues, NoCases+1);
SetLength(Means, NoSelected+1);
SetLength(Variances, NoSelected+1);
SetLength(StdDevs, NoSelected+1);
SetLength(RMatrix, NoSelected+1, NoSelected+1);
SetLength(selected, NoVariables);
for i := 0 to NoSelected - 1 do
begin
Means[i] := 0.0;
StdDevs[i] := 0.0;
for j := 0 to NoSelected-1 do RMatrix[i,j] := 0.0;
end;
for i := 1 to NoCases do
begin
if not GoodRecord(i,NoSelected,selected) then continue;
XValues[i] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[XCol,i]));
if XValues[i] > MaxX then MaxX := XValues[i];
if XValues[i] < MinX then MinX := XValues[i];
for j := 0 to NoY - 1 do
begin
YValues[i-1,j] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[selected[j],i]));
if YValues[i-1,j] > MaxY then MaxY := YValues[i-1,j];
if YValues[i-1,j] < MinY then MinY := YValues[i-1,j];
end;
end;
// get descriptive data
if DescChk.Checked then
begin
Correlations(NoSelected,selected,RMatrix,Means,Variances,StdDevs,errorcode,Ncases);
N := Ncases;
Title := 'CORRELATIONS';
MatPrint(RMatrix, NoSelected, NoSelected, Title, RowLabels, ColLabels, N, lReport);
Title := 'Means';
DynVectorPrint(Means, NoSelected, Title, RowLabels, N, lReport);
Title := 'Variances';
DynVectorPrint(Variances, NoSelected, Title, RowLabels, N, lReport);
Title := 'Standard Deviations';
DynVectorPrint(StdDevs, NoSelected, Title, RowLabels, N, lReport);
end;
DisplayReport(lReport);
// sort on X
for i := 0 to N-2 do
begin
for j := i+1 to N-1 do
begin
if XValues[i] > XValues[j] then // swap
begin
temp := XValues[i];
XValues[i] := XValues[j];
XValues[j] := temp;
for k := 0 to NoY-1 do
begin
temp := YValues[i,k];
YValues[i,k] := YValues[j,k];
YValues[j,k] := temp;
end;
end;
end;
end;
PlotXY(XValues, YValues, MaxX, MinX, MaxY, MinY, N, NoY);
finally
lReport.Free;
RMatrix := nil;
StdDevs := nil;
Variances := nil;
Means := nil;
XValues := nil;
YValues := nil;
selected := nil;
ColLabels := nil;
RowLabels := nil;
end;
end;
procedure TXvsMultYForm.FormActivate(Sender: TObject);
var
w: 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;
Constraints.MinWidth := Width;
Constraints.MinHeight := Height;
FAutoSized := true;
end;
procedure TXvsMultYForm.FormCreate(Sender: TObject);
begin
Assert(OS3MainFrm <> nil);
if BlankFrm = nil then
Application.CreateForm(TBlankFrm, BlankFrm);
end;
procedure TXvsMultYForm.XInBtnClick(Sender: TObject);
var
index: integer;
begin
index := VarList.ItemIndex;
if (index > -1) and (XEdit.Text = '') then
begin
XEdit.Text := VarList.Items[index];
VarList.Items.Delete(index);
end;
UpdateBtnStates;
end;
procedure TXvsMultYForm.XOutBtnClick(Sender: TObject);
begin
if (XEdit.Text <> '') then
begin
VarList.Items.Add(XEdit.Text);
XEdit.Text := '';
end;
UpdateBtnStates;
end;
procedure TXvsMultYForm.YInBtnClick(Sender: TObject);
var
i: integer;
begin
i := 0;
while i < VarList.Items.Count do
begin
if VarList.Selected[i] then
begin
YBox.Items.Add(VarList.Items[i]);
VarList.Items.Delete(i);
i := 0;
end else
inc(i);
end;
UpdateBtnStates;
end;
procedure TXvsMultYForm.YOutBtnClick(Sender: TObject);
var
i: integer;
begin
i := 0;
while i < YBox.Items.Count do
begin
if (YBox.Selected[i]) then
begin
VarList.Items.Add(YBox.Items[i]);
YBox.Items.Delete(i);
i := 0;
end else
i := i + 1;
end;
UpdateBtnStates;
end;
// routine to plot X versus multiple Y values
procedure TXvsMultYForm.PlotXY(XValues: DblDyneVec; YValues: DblDyneMat;
MaxX, MinX, MaxY, MinY: double; N, NoY: integer);
var
i, j, xpos, ypos, hleft, hright, vtop, vbottom, imagewide: integer;
vhi, hwide, offset, strhi, imagehi: integer;
valincr, Yvalue, Xvalue: double;
Title: string;
begin
Title := PlotTitleEdit.Text;
BlankFrm.Caption := Title;
BlankFrm.Show;
imagewide := BlankFrm.Image1.Width;
imagehi := BlankFrm.Image1.Height;
vtop := 40;
vbottom := round(imagehi) - 60;
vhi := vbottom - vtop;
hleft := 100;
hright := imagewide - 80;
hwide := hright - hleft;
// Draw chart border and background
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
BlankFrm.Image1.Canvas.Rectangle(0, 0, imagewide, imagehi);
// Draw title
Title := PlotTitleEdit.Text;
if Title <> '' then
begin
xpos := (imagewide - BlankFrm.Image1.Canvas.TextWidth(Title)) div 2;
yPos := 2;
BlankFrm.Image1.Canvas.TextOut(xpos, ypos, Title);
end;
// draw horizontal axis
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
BlankFrm.Image1.Canvas.MoveTo(hleft,vbottom);
BlankFrm.Image1.Canvas.LineTo(hright,vbottom);
valincr := (maxX - minX) / 10.0;
for i := 1 to 11 do
begin
ypos := vbottom;
Xvalue := minX + valincr * (i - 1);
xpos := hleft + round(hwide * ((Xvalue - minX) / (maxX - minX)));
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;
xpos := hleft + (hwide - BlankFrm.Image1.Canvas.TextWidth(XEdit.Text)) div 2;
ypos := vbottom + 30;
BlankFrm.Image1.Canvas.TextOut(xpos, ypos, XEdit.Text);
// draw vertical axis
Title := 'Y VALUES';
xpos := hleft - BlankFrm.Image1.Canvas.TextWidth(Title) div 2;
ypos := 8;
BlankFrm.Image1.Canvas.TextOut(xpos, ypos, Title);
xpos := hleft;
ypos := vtop;
BlankFrm.Image1.Canvas.MoveTo(xpos, ypos);
ypos := vbottom;
BlankFrm.Image1.Canvas.LineTo(xpos, ypos);
valincr := (maxY - minY) / 10.0;
for i := 1 to 11 do
begin
Title := Format('%.2f',[maxY - ((i-1)*valincr)]);
strhi := BlankFrm.Image1.Canvas.TextHeight(Title);
xpos := hleft - 20 - BlankFrm.Image1.Canvas.TextWidth(Title);
Yvalue := maxY - (valincr * (i-1));
ypos := round(vhi * ( (maxY - Yvalue) / (maxY - minY)));
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 j := 0 to NoY-1 do
begin
BlankFrm.Image1.Canvas.Brush.Style := bsSolid;
BlankFrm.Image1.Canvas.Brush.Color := DATA_COLORS[j mod Length(DATA_COLORS)];
BlankFrm.Image1.Canvas.Pen.Color := DATA_COLORS[j mod Length(DATA_COLORS)];
BlankFrm.Image1.Canvas.Font.Color := DATA_COLORS[j mod Length(DATA_COLORS)];
Title := Trim(OS3MainFrm.DataGrid.Cells[selected[j],0]);
for i := 1 to N do
begin
ypos := vtop + round(vhi * ( (maxY - YValues[i-1,j]) / (maxY - minY)));
xpos := hleft + round(hwide * ( (XValues[i-1]-minX) / (maxX - minX)));
if xpos < hleft then xpos := hleft;
if i = 1 then
BlankFrm.Image1.Canvas.MoveTo(xpos, ypos);
if LinesBox.Checked then
BlankFrm.Image1.Canvas.LineTo(xpos, ypos);
BlankFrm.Image1.Canvas.Ellipse(xpos, ypos, xpos+5, ypos+5);
end;
strhi := BlankFrm.Image1.Canvas.TextHeight(Title);
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
xpos := hwide + hleft;
BlankFrm.Image1.Canvas.MoveTo(xpos, ypos-strhi);
BlankFrm.Image1.Canvas.TextOut(xpos, ypos, Title);
end;
BlankFrm.Image1.Canvas.Font.Color := clBlack;
end;
procedure TXvsMultYForm.UpdateBtnStates;
var
lSelected: Boolean;
begin
lSelected := AnySelected(VarList);
XInBtn.Enabled := lSelected and (XEdit.Text = '');
YInBtn.Enabled := lSelected;
xOutBtn.Enabled := (XEdit.Text <> '');
YOutBtn.Enabled := AnySelected(YBox);
end;
initialization
{$I xvsmultyunit.lrs}
end.