ML - рефакторинг Clone, IsValid
This commit is contained in:
parent
9cf33b094c
commit
94927c73e1
|
|
@ -1,6 +1,11 @@
|
|||
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
// DataFrameABC v.1.1
|
||||
// =============================================================
|
||||
// СТАТИСТИЧЕСКОЕ СОГЛАШЕНИЕ (DataFrame)
|
||||
//
|
||||
// Используется выборочная дисперсия (деление на n - 1),
|
||||
// как принято в описательной статистике.
|
||||
//
|
||||
// См. статистическую политику в модуле MLABC.
|
||||
// =============================================================
|
||||
|
||||
/// Стандартный модуль для работы с табличными данными (датасетами)
|
||||
/// !! DataFrame module for tabular data processing
|
||||
|
|
@ -95,7 +100,6 @@ type
|
|||
function GetColumn(name: string): Column;
|
||||
|
||||
function CloneWithCopiedColumns: DataFrame;
|
||||
static procedure EnsureValidArray(var valid: array of boolean; rowCount, filledCount: integer);
|
||||
public
|
||||
/// Создает пустой DataFrame
|
||||
constructor Create;
|
||||
|
|
@ -692,17 +696,17 @@ begin
|
|||
if li >= 0 then
|
||||
begin
|
||||
data[i] := leftCol.Data[li];
|
||||
valid[i] := if leftCol.IsValid = nil then true else leftCol.IsValid[li];
|
||||
valid[i] := leftCol.IsValid[li];
|
||||
end
|
||||
else if ri >= 0 then
|
||||
begin
|
||||
data[i] := rightCol.Data[ri];
|
||||
valid[i] := if rightCol.IsValid = nil then true else rightCol.IsValid[ri];
|
||||
valid[i] := rightCol.IsValid[ri];
|
||||
end
|
||||
else
|
||||
begin
|
||||
data[i] := 0;
|
||||
valid[i] := false;
|
||||
valid[i] := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
@ -729,17 +733,17 @@ begin
|
|||
if li >= 0 then
|
||||
begin
|
||||
data[i] := leftCol.Data[li];
|
||||
valid[i] := if leftCol.IsValid = nil then true else leftCol.IsValid[li];
|
||||
valid[i] := leftCol.IsValid[li];
|
||||
end
|
||||
else if ri >= 0 then
|
||||
begin
|
||||
data[i] := rightCol.Data[ri];
|
||||
valid[i] := if rightCol.IsValid = nil then true else rightCol.IsValid[ri];
|
||||
valid[i] := rightCol.IsValid[ri];
|
||||
end
|
||||
else
|
||||
begin
|
||||
data[i] := 0.0;
|
||||
valid[i] := false;
|
||||
valid[i] := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
@ -766,17 +770,17 @@ begin
|
|||
if li >= 0 then
|
||||
begin
|
||||
data[i] := leftCol.Data[li];
|
||||
valid[i] := if leftCol.IsValid = nil then true else leftCol.IsValid[li];
|
||||
valid[i] := leftCol.IsValid[li];
|
||||
end
|
||||
else if ri >= 0 then
|
||||
begin
|
||||
data[i] := rightCol.Data[ri];
|
||||
valid[i] := if rightCol.IsValid = nil then true else rightCol.IsValid[ri];
|
||||
valid[i] := rightCol.IsValid[ri];
|
||||
end
|
||||
else
|
||||
begin
|
||||
data[i] := '';
|
||||
valid[i] := false;
|
||||
valid[i] := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
@ -803,12 +807,12 @@ begin
|
|||
if li >= 0 then
|
||||
begin
|
||||
data[i] := leftCol.Data[li];
|
||||
valid[i] := if leftCol.IsValid = nil then true else leftCol.IsValid[li];
|
||||
valid[i] := leftCol.IsValid[li];
|
||||
end
|
||||
else if ri >= 0 then
|
||||
begin
|
||||
data[i] := rightCol.Data[ri];
|
||||
valid[i] := if rightCol.IsValid = nil then true else rightCol.IsValid[ri];
|
||||
valid[i] := rightCol.IsValid[ri];
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
|
@ -838,12 +842,12 @@ begin
|
|||
if j < 0 then
|
||||
begin
|
||||
data[i] := 0;
|
||||
valid[i] := false;
|
||||
valid[i] := False;
|
||||
end
|
||||
else
|
||||
begin
|
||||
data[i] := src.Data[j];
|
||||
valid[i] := if src.IsValid = nil then true else src.IsValid[j];
|
||||
valid[i] := src.IsValid[j];
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
@ -868,12 +872,12 @@ begin
|
|||
if j < 0 then
|
||||
begin
|
||||
data[i] := 0.0;
|
||||
valid[i] := false;
|
||||
valid[i] := False;
|
||||
end
|
||||
else
|
||||
begin
|
||||
data[i] := src.Data[j];
|
||||
valid[i] := if src.IsValid = nil then true else src.IsValid[j];
|
||||
valid[i] := src.IsValid[j];
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
@ -898,12 +902,12 @@ begin
|
|||
if j < 0 then
|
||||
begin
|
||||
data[i] := '';
|
||||
valid[i] := false;
|
||||
valid[i] := False;
|
||||
end
|
||||
else
|
||||
begin
|
||||
data[i] := src.Data[j];
|
||||
valid[i] := if src.IsValid = nil then true else src.IsValid[j];
|
||||
valid[i] := src.IsValid[j];
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
@ -927,13 +931,13 @@ begin
|
|||
|
||||
if j < 0 then
|
||||
begin
|
||||
data[i] := false;
|
||||
valid[i] := false;
|
||||
data[i] := False;
|
||||
valid[i] := False;
|
||||
end
|
||||
else
|
||||
begin
|
||||
data[i] := src.Data[j];
|
||||
valid[i] := if src.IsValid = nil then true else src.IsValid[j];
|
||||
valid[i] := src.IsValid[j];
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
@ -2223,21 +2227,10 @@ end;
|
|||
|
||||
procedure DataFrame.AddIntColumn(name: string; data: array of integer; valid: array of boolean);
|
||||
begin
|
||||
if (columns.Count > 0) and (data.Length <> RowCount) then
|
||||
if (columns.Count > 0) and (Length(data) <> RowCount) then
|
||||
DimensionError(ER_ADD_COLUMN_ROW_MISMATCH);
|
||||
|
||||
var c := new IntColumn;
|
||||
c.Info := new ColumnInfo(name, ctInt);
|
||||
c.Data := data;
|
||||
|
||||
if valid = nil then
|
||||
c.IsValid := [True] * data.Length
|
||||
else
|
||||
begin
|
||||
if valid.Length <> data.Length then
|
||||
DimensionError(ER_COLUMN_VALID_LENGTH_MISMATCH);
|
||||
c.IsValid := valid;
|
||||
end;
|
||||
var c := new IntColumn(name, data, valid);
|
||||
|
||||
columns.Add(c);
|
||||
RebuildSchema;
|
||||
|
|
@ -2245,21 +2238,10 @@ end;
|
|||
|
||||
procedure DataFrame.AddFloatColumn(name: string; data: array of real; valid: array of boolean);
|
||||
begin
|
||||
if (columns.Count > 0) and (data.Length <> RowCount) then
|
||||
if (columns.Count > 0) and (Length(data) <> RowCount) then
|
||||
DimensionError(ER_ADD_COLUMN_ROW_MISMATCH);
|
||||
|
||||
var c := new FloatColumn;
|
||||
c.Info := new ColumnInfo(name, ctFloat);
|
||||
c.Data := data;
|
||||
|
||||
if valid = nil then
|
||||
c.IsValid := [True] * data.Length
|
||||
else
|
||||
begin
|
||||
if valid.Length <> data.Length then
|
||||
DimensionError(ER_COLUMN_VALID_LENGTH_MISMATCH);
|
||||
c.IsValid := valid;
|
||||
end;
|
||||
var c := new FloatColumn(name, data, valid);
|
||||
|
||||
columns.Add(c);
|
||||
RebuildSchema;
|
||||
|
|
@ -2267,21 +2249,10 @@ end;
|
|||
|
||||
procedure DataFrame.AddStrColumn(name: string; data: array of string; valid: array of boolean);
|
||||
begin
|
||||
if (columns.Count > 0) and (data.Length <> RowCount) then
|
||||
if (columns.Count > 0) and (Length(data) <> RowCount) then
|
||||
DimensionError(ER_ADD_COLUMN_ROW_MISMATCH);
|
||||
|
||||
var c := new StrColumn;
|
||||
c.Info := new ColumnInfo(name, ctStr);
|
||||
c.Data := data;
|
||||
|
||||
if valid = nil then
|
||||
c.IsValid := [True] * data.Length
|
||||
else
|
||||
begin
|
||||
if valid.Length <> data.Length then
|
||||
DimensionError(ER_COLUMN_VALID_LENGTH_MISMATCH);
|
||||
c.IsValid := valid;
|
||||
end;
|
||||
var c := new StrColumn(name, data, valid);
|
||||
|
||||
columns.Add(c);
|
||||
RebuildSchema;
|
||||
|
|
@ -2295,27 +2266,15 @@ end;
|
|||
|
||||
procedure DataFrame.AddBoolColumn(name: string; data: array of boolean; valid: array of boolean);
|
||||
begin
|
||||
if (columns.Count > 0) and (data.Length <> RowCount) then
|
||||
if (columns.Count > 0) and (Length(data) <> RowCount) then
|
||||
DimensionError(ER_ADD_COLUMN_ROW_MISMATCH);
|
||||
|
||||
var c := new BoolColumn;
|
||||
c.Info := new ColumnInfo(name, ctBool);
|
||||
c.Data := data;
|
||||
|
||||
if valid = nil then
|
||||
c.IsValid := [True] * data.Length
|
||||
else
|
||||
begin
|
||||
if valid.Length <> data.Length then
|
||||
DimensionError(ER_COLUMN_VALID_LENGTH_MISMATCH);
|
||||
c.IsValid := valid;
|
||||
end;
|
||||
var c := new BoolColumn(name, data, valid);
|
||||
|
||||
columns.Add(c);
|
||||
RebuildSchema;
|
||||
end;
|
||||
|
||||
|
||||
procedure DataFrame.CheckColumnIndex(colIndex: integer);
|
||||
begin
|
||||
if (colIndex < 0) or (colIndex >= ColumnCount) then
|
||||
|
|
@ -2917,16 +2876,12 @@ begin
|
|||
var src := IntColumn(col);
|
||||
|
||||
var data := new integer[newCount];
|
||||
var valid: array of boolean := nil;
|
||||
|
||||
if src.IsValid <> nil then
|
||||
valid := new boolean[newCount];
|
||||
var valid := new boolean[newCount];
|
||||
|
||||
for var k := 0 to newCount - 1 do
|
||||
begin
|
||||
var i := mask[k];
|
||||
data[k] := src.Data[i];
|
||||
if valid <> nil then
|
||||
valid[k] := src.IsValid[i];
|
||||
end;
|
||||
|
||||
|
|
@ -2939,16 +2894,12 @@ begin
|
|||
var src := FloatColumn(col);
|
||||
|
||||
var data := new real[newCount];
|
||||
var valid: array of boolean := nil;
|
||||
|
||||
if src.IsValid <> nil then
|
||||
valid := new boolean[newCount];
|
||||
var valid := new boolean[newCount];
|
||||
|
||||
for var k := 0 to newCount - 1 do
|
||||
begin
|
||||
var i := mask[k];
|
||||
data[k] := src.Data[i];
|
||||
if valid <> nil then
|
||||
valid[k] := src.IsValid[i];
|
||||
end;
|
||||
|
||||
|
|
@ -2961,16 +2912,12 @@ begin
|
|||
var src := StrColumn(col);
|
||||
|
||||
var data := new string[newCount];
|
||||
var valid: array of boolean := nil;
|
||||
|
||||
if src.IsValid <> nil then
|
||||
valid := new boolean[newCount];
|
||||
var valid := new boolean[newCount];
|
||||
|
||||
for var k := 0 to newCount - 1 do
|
||||
begin
|
||||
var i := mask[k];
|
||||
data[k] := src.Data[i];
|
||||
if valid <> nil then
|
||||
valid[k] := src.IsValid[i];
|
||||
end;
|
||||
|
||||
|
|
@ -2983,16 +2930,12 @@ begin
|
|||
var src := BoolColumn(col);
|
||||
|
||||
var data := new boolean[newCount];
|
||||
var valid: array of boolean := nil;
|
||||
|
||||
if src.IsValid <> nil then
|
||||
valid := new boolean[newCount];
|
||||
var valid := new boolean[newCount];
|
||||
|
||||
for var k := 0 to newCount - 1 do
|
||||
begin
|
||||
var i := mask[k];
|
||||
data[k] := src.Data[i];
|
||||
if valid <> nil then
|
||||
valid[k] := src.IsValid[i];
|
||||
end;
|
||||
|
||||
|
|
@ -3251,16 +3194,6 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
static procedure DataFrame.EnsureValidArray(var valid: array of boolean; rowCount, filledCount: integer);
|
||||
begin
|
||||
if valid = nil then
|
||||
begin
|
||||
valid := new boolean[rowCount];
|
||||
for var j := 0 to filledCount - 1 do
|
||||
valid[j] := true;
|
||||
end;
|
||||
end;
|
||||
|
||||
function DataFrame.WithColumnInt(name: string; f: DataFrameCursor -> integer): DataFrame;
|
||||
begin
|
||||
if fSchema.HasColumn(name) then
|
||||
|
|
@ -3269,7 +3202,7 @@ begin
|
|||
var res := CloneWithCopiedColumns;
|
||||
|
||||
var data := new integer[RowCount];
|
||||
var valid: array of boolean := nil;
|
||||
var valid := new boolean[RowCount];
|
||||
|
||||
var cur := GetCursor;
|
||||
var i := 0;
|
||||
|
|
@ -3282,15 +3215,13 @@ begin
|
|||
on e: Exception do
|
||||
begin
|
||||
data[i] := 0;
|
||||
EnsureValidArray(valid, RowCount, i);
|
||||
valid[i] := false;
|
||||
valid[i] := False;
|
||||
i += 1;
|
||||
continue;
|
||||
end;
|
||||
end;
|
||||
|
||||
if valid <> nil then
|
||||
valid[i] := true;
|
||||
valid[i] := True;
|
||||
|
||||
i += 1;
|
||||
end;
|
||||
|
|
@ -3310,7 +3241,7 @@ begin
|
|||
var res := CloneWithCopiedColumns;
|
||||
|
||||
var data := new real[RowCount];
|
||||
var valid: array of boolean := nil;
|
||||
var valid := new boolean[RowCount];
|
||||
|
||||
var cur := GetCursor;
|
||||
var i := 0;
|
||||
|
|
@ -3323,15 +3254,13 @@ begin
|
|||
on e: Exception do
|
||||
begin
|
||||
data[i] := 0.0;
|
||||
EnsureValidArray(valid, RowCount, i);
|
||||
valid[i] := false;
|
||||
valid[i] := False;
|
||||
i += 1;
|
||||
continue;
|
||||
end;
|
||||
end;
|
||||
|
||||
if valid <> nil then
|
||||
valid[i] := true;
|
||||
valid[i] := True;
|
||||
|
||||
i += 1;
|
||||
end;
|
||||
|
|
@ -3351,7 +3280,7 @@ begin
|
|||
var res := CloneWithCopiedColumns;
|
||||
|
||||
var data := new string[RowCount];
|
||||
var valid: array of boolean := nil;
|
||||
var valid := new boolean[RowCount];
|
||||
|
||||
var cur := GetCursor;
|
||||
var i := 0;
|
||||
|
|
@ -3364,15 +3293,13 @@ begin
|
|||
on e: Exception do
|
||||
begin
|
||||
data[i] := nil;
|
||||
EnsureValidArray(valid, RowCount, i);
|
||||
valid[i] := false;
|
||||
valid[i] := False;
|
||||
i += 1;
|
||||
continue;
|
||||
end;
|
||||
end;
|
||||
|
||||
if valid <> nil then
|
||||
valid[i] := true;
|
||||
valid[i] := True;
|
||||
|
||||
i += 1;
|
||||
end;
|
||||
|
|
@ -3392,7 +3319,7 @@ begin
|
|||
var res := CloneWithCopiedColumns;
|
||||
|
||||
var data := new boolean[RowCount];
|
||||
var valid: array of boolean := nil;
|
||||
var valid := new boolean[RowCount];
|
||||
|
||||
var cur := GetCursor;
|
||||
var i := 0;
|
||||
|
|
@ -3404,16 +3331,14 @@ begin
|
|||
except
|
||||
on e: Exception do
|
||||
begin
|
||||
data[i] := false;
|
||||
EnsureValidArray(valid, RowCount, i);
|
||||
valid[i] := false;
|
||||
data[i] := False;
|
||||
valid[i] := False;
|
||||
i += 1;
|
||||
continue;
|
||||
end;
|
||||
end;
|
||||
|
||||
if valid <> nil then
|
||||
valid[i] := true;
|
||||
valid[i] := True;
|
||||
|
||||
i += 1;
|
||||
end;
|
||||
|
|
@ -3458,7 +3383,7 @@ begin
|
|||
var rowCount := RowCount;
|
||||
|
||||
var data := new real[rowCount];
|
||||
var valid: array of boolean := nil;
|
||||
var valid := new boolean[rowCount];
|
||||
|
||||
var cur := GetCursor;
|
||||
var row := 0;
|
||||
|
|
@ -3469,14 +3394,6 @@ begin
|
|||
if not cur.IsValid(colIndex) then
|
||||
begin
|
||||
data[row] := 0.0;
|
||||
|
||||
if valid = nil then
|
||||
begin
|
||||
valid := new boolean[rowCount];
|
||||
for var j := 0 to row - 1 do
|
||||
valid[j] := true;
|
||||
end;
|
||||
|
||||
valid[row] := false;
|
||||
row += 1;
|
||||
continue;
|
||||
|
|
@ -3489,22 +3406,13 @@ begin
|
|||
on e: Exception do
|
||||
begin
|
||||
data[row] := 0.0;
|
||||
|
||||
if valid = nil then
|
||||
begin
|
||||
valid := new boolean[rowCount];
|
||||
for var j := 0 to row - 1 do
|
||||
valid[j] := true;
|
||||
end;
|
||||
|
||||
valid[row] := false;
|
||||
valid[row] := False;
|
||||
row += 1;
|
||||
continue;
|
||||
end;
|
||||
end;
|
||||
|
||||
if valid <> nil then
|
||||
valid[row] := true;
|
||||
valid[row] := True;
|
||||
|
||||
row += 1;
|
||||
end;
|
||||
|
|
@ -3540,7 +3448,7 @@ begin
|
|||
var rowCount := RowCount;
|
||||
|
||||
var data := new integer[rowCount];
|
||||
var valid: array of boolean := nil;
|
||||
var valid := new boolean[rowCount];
|
||||
|
||||
var cur := GetCursor;
|
||||
var row := 0;
|
||||
|
|
@ -3548,17 +3456,12 @@ begin
|
|||
begin
|
||||
try
|
||||
data[row] := f(cur);
|
||||
if valid <> nil then valid[row] := true;
|
||||
valid[row] := True;
|
||||
except
|
||||
on e: Exception do
|
||||
begin
|
||||
data[row] := 0;
|
||||
if valid = nil then
|
||||
begin
|
||||
valid := new boolean[rowCount];
|
||||
for var j := 0 to row - 1 do valid[j] := true;
|
||||
end;
|
||||
valid[row] := false;
|
||||
valid[row] := False;
|
||||
end;
|
||||
end;
|
||||
row += 1;
|
||||
|
|
@ -3597,7 +3500,7 @@ begin
|
|||
|
||||
var rowCount := RowCount;
|
||||
var data := new integer[rowCount];
|
||||
var valid: array of boolean := nil;
|
||||
var valid := new boolean[rowCount];
|
||||
|
||||
var cur := GetCursor;
|
||||
var row := 0;
|
||||
|
|
@ -3605,17 +3508,12 @@ begin
|
|||
begin
|
||||
try
|
||||
data[row] := f(cur);
|
||||
if valid <> nil then valid[row] := true;
|
||||
valid[row] := True;
|
||||
except
|
||||
on e: Exception do
|
||||
begin
|
||||
data[row] := 0;
|
||||
if valid = nil then
|
||||
begin
|
||||
valid := new boolean[rowCount];
|
||||
for var j := 0 to row - 1 do valid[j] := true;
|
||||
end;
|
||||
valid[row] := false;
|
||||
valid[row] := False;
|
||||
end;
|
||||
end;
|
||||
row += 1;
|
||||
|
|
@ -3863,11 +3761,7 @@ begin
|
|||
begin
|
||||
var src := IntColumn(col);
|
||||
var data := new integer[k];
|
||||
var validSrc := src.IsValid;
|
||||
var validDst: array of boolean := nil;
|
||||
|
||||
if validSrc <> nil then
|
||||
validDst := new boolean[k];
|
||||
var validDst := new boolean[k];
|
||||
|
||||
for var j := 0 to k - 1 do
|
||||
begin
|
||||
|
|
@ -3876,15 +3770,8 @@ begin
|
|||
if (i < 0) or (i >= RowCount) then
|
||||
ArgumentError(ER_ROW_INDEX_OUT_OF_RANGE, i);
|
||||
|
||||
if validSrc = nil then
|
||||
data[j] := src.Data[i]
|
||||
else if validSrc[i] then
|
||||
begin
|
||||
data[j] := src.Data[i];
|
||||
validDst[j] := true;
|
||||
end
|
||||
else
|
||||
validDst[j] := false;
|
||||
validDst[j] := src.IsValid[i];
|
||||
end;
|
||||
|
||||
res.AddIntColumn(name, data, validDst);
|
||||
|
|
@ -3894,11 +3781,7 @@ begin
|
|||
begin
|
||||
var src := FloatColumn(col);
|
||||
var data := new real[k];
|
||||
var validSrc := src.IsValid;
|
||||
var validDst: array of boolean := nil;
|
||||
|
||||
if validSrc <> nil then
|
||||
validDst := new boolean[k];
|
||||
var validDst := new boolean[k];
|
||||
|
||||
for var j := 0 to k - 1 do
|
||||
begin
|
||||
|
|
@ -3907,15 +3790,8 @@ begin
|
|||
if (i < 0) or (i >= RowCount) then
|
||||
ArgumentError(ER_ROW_INDEX_OUT_OF_RANGE, i);
|
||||
|
||||
if validSrc = nil then
|
||||
data[j] := src.Data[i]
|
||||
else if validSrc[i] then
|
||||
begin
|
||||
data[j] := src.Data[i];
|
||||
validDst[j] := true;
|
||||
end
|
||||
else
|
||||
validDst[j] := false;
|
||||
validDst[j] := src.IsValid[i];
|
||||
end;
|
||||
|
||||
res.AddFloatColumn(name, data, validDst);
|
||||
|
|
@ -3925,11 +3801,7 @@ begin
|
|||
begin
|
||||
var src := StrColumn(col);
|
||||
var data := new string[k];
|
||||
var validSrc := src.IsValid;
|
||||
var validDst: array of boolean := nil;
|
||||
|
||||
if validSrc <> nil then
|
||||
validDst := new boolean[k];
|
||||
var validDst := new boolean[k];
|
||||
|
||||
for var j := 0 to k - 1 do
|
||||
begin
|
||||
|
|
@ -3938,15 +3810,8 @@ begin
|
|||
if (i < 0) or (i >= RowCount) then
|
||||
ArgumentError(ER_ROW_INDEX_OUT_OF_RANGE, i);
|
||||
|
||||
if validSrc = nil then
|
||||
data[j] := src.Data[i]
|
||||
else if validSrc[i] then
|
||||
begin
|
||||
data[j] := src.Data[i];
|
||||
validDst[j] := true;
|
||||
end
|
||||
else
|
||||
validDst[j] := false;
|
||||
validDst[j] := src.IsValid[i];
|
||||
end;
|
||||
|
||||
res.AddStrColumn(name, data, validDst);
|
||||
|
|
@ -3956,11 +3821,7 @@ begin
|
|||
begin
|
||||
var src := BoolColumn(col);
|
||||
var data := new boolean[k];
|
||||
var validSrc := src.IsValid;
|
||||
var validDst: array of boolean := nil;
|
||||
|
||||
if validSrc <> nil then
|
||||
validDst := new boolean[k];
|
||||
var validDst := new boolean[k];
|
||||
|
||||
for var j := 0 to k - 1 do
|
||||
begin
|
||||
|
|
@ -3969,15 +3830,8 @@ begin
|
|||
if (i < 0) or (i >= RowCount) then
|
||||
ArgumentError(ER_ROW_INDEX_OUT_OF_RANGE, i);
|
||||
|
||||
if validSrc = nil then
|
||||
data[j] := src.Data[i]
|
||||
else if validSrc[i] then
|
||||
begin
|
||||
data[j] := src.Data[i];
|
||||
validDst[j] := true;
|
||||
end
|
||||
else
|
||||
validDst[j] := false;
|
||||
validDst[j] := src.IsValid[i];
|
||||
end;
|
||||
|
||||
res.AddBoolColumn(name, data, validDst);
|
||||
|
|
@ -4305,13 +4159,10 @@ begin
|
|||
case src.Info.ColType of
|
||||
ctInt:
|
||||
AddIntColumn(src.Info.Name, IntColumn(src).Data, IntColumn(src).IsValid);
|
||||
|
||||
ctFloat:
|
||||
AddFloatColumn(src.Info.Name, FloatColumn(src).Data, FloatColumn(src).IsValid);
|
||||
|
||||
ctStr:
|
||||
AddStrColumn(src.Info.Name, StrColumn(src).Data, StrColumn(src).IsValid);
|
||||
|
||||
ctBool:
|
||||
AddBoolColumn(src.Info.Name, BoolColumn(src).Data, BoolColumn(src).IsValid);
|
||||
end;
|
||||
|
|
@ -4559,7 +4410,7 @@ begin
|
|||
begin
|
||||
var i := indices[j];
|
||||
|
||||
if (valid <> nil) and not valid[i] then
|
||||
if not valid[i] then
|
||||
continue;
|
||||
|
||||
s += if isInt then dataInt[i] else dataFloat[i];
|
||||
|
|
@ -4586,7 +4437,7 @@ begin
|
|||
begin
|
||||
var i := indices[j];
|
||||
|
||||
if (valid <> nil) and not valid[i] then
|
||||
if not valid[i] then
|
||||
continue;
|
||||
|
||||
s += if isInt then dataInt[i] else dataFloat[i];
|
||||
|
|
@ -4614,7 +4465,7 @@ begin
|
|||
begin
|
||||
var i := indices[j];
|
||||
|
||||
if (valid <> nil) and not valid[i] then
|
||||
if not valid[i] then
|
||||
continue;
|
||||
|
||||
var v := if isInt then dataInt[i] else dataFloat[i];
|
||||
|
|
@ -4647,7 +4498,7 @@ begin
|
|||
begin
|
||||
var i := indices[j];
|
||||
|
||||
if (valid <> nil) and not valid[i] then
|
||||
if not valid[i] then
|
||||
continue;
|
||||
|
||||
var v := if isInt then dataInt[i] else dataFloat[i];
|
||||
|
|
@ -5578,7 +5429,7 @@ begin
|
|||
if cur.IsValid(i) then
|
||||
col.Data[row] := (cur.Float(i) - means[i]) / stds[i]
|
||||
else
|
||||
col.IsValid[row] := false;
|
||||
col.IsValid[row] := False;
|
||||
|
||||
end;
|
||||
row += 1;
|
||||
|
|
@ -5661,20 +5512,11 @@ begin
|
|||
if cur.IsValid(i) then
|
||||
begin
|
||||
col.Data[row] := (cur.Float(i) - mins[i]) / (maxs[i] - mins[i]);
|
||||
if col.IsValid <> nil then
|
||||
col.IsValid[row] := true;
|
||||
col.IsValid[row] := True;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// первый NA → создаём IsValid
|
||||
if col.IsValid = nil then
|
||||
begin
|
||||
col.IsValid := new boolean[df.RowCount];
|
||||
for var r := 0 to row - 1 do
|
||||
col.IsValid[r] := true;
|
||||
end;
|
||||
col.IsValid[row] := false;
|
||||
end;
|
||||
col.IsValid[row] := False;
|
||||
end;
|
||||
row += 1;
|
||||
end;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,20 @@
|
|||
unit DataFrameABCCore;
|
||||
|
||||
// =============================================================
|
||||
// ИНВАРИАНТ ВАЛИДНОСТИ СТОЛБЦОВ
|
||||
//
|
||||
// Для всех столбцов:
|
||||
// • IsValid всегда инициализирован
|
||||
// • Length(IsValid) = Length(Data)
|
||||
// • nil не используется как специальное значение
|
||||
//
|
||||
// Пустой столбец:
|
||||
// • Data имеет длину 0
|
||||
// • IsValid = new boolean[0]
|
||||
//
|
||||
// Нарушение этого инварианта считается ошибкой.
|
||||
// =============================================================
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
|
|
@ -276,6 +291,8 @@ const
|
|||
ER_ROW_INDEX_OUT_OF_RANGE =
|
||||
'Индекс строки {0} вне диапазона [0..{1})!!' +
|
||||
'Row index {0} out of range [0..{1})';
|
||||
ER_INVALID_ISVALID_LENGTH =
|
||||
'Длина IsValid должна совпадать с длиной Data!!IsValid length must match Data length';
|
||||
|
||||
//-----------------------------
|
||||
// Сервисные функции
|
||||
|
|
@ -547,142 +564,155 @@ end;
|
|||
// Columns
|
||||
//-----------------------------
|
||||
|
||||
constructor IntColumn.Create(name: string; data: array of integer;
|
||||
valid: array of boolean);
|
||||
constructor IntColumn.Create(name: string; data: array of integer; valid: array of boolean);
|
||||
begin
|
||||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctInt);
|
||||
|
||||
Data := data;
|
||||
var n := Length(data);
|
||||
Data := if n = 0 then [] else data;
|
||||
|
||||
if valid = nil then
|
||||
IsValid := [True] * n
|
||||
else
|
||||
begin
|
||||
if Length(valid) <> n then
|
||||
Error(ER_INVALID_ISVALID_LENGTH);
|
||||
|
||||
IsValid := valid;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor IntColumn.Create(name: string);
|
||||
begin
|
||||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctInt);
|
||||
|
||||
Data := new integer[0];
|
||||
IsValid := nil;
|
||||
Data := [];
|
||||
IsValid := [];
|
||||
end;
|
||||
|
||||
function IntColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
||||
begin
|
||||
if (IsValid <> nil) and not IsValid[i] then
|
||||
exit(false);
|
||||
if not IsValid[i] then
|
||||
exit(False);
|
||||
|
||||
value := Data[i];
|
||||
exit(true);
|
||||
exit(True);
|
||||
end;
|
||||
|
||||
constructor FloatColumn.Create(name: string; data: array of real;
|
||||
valid: array of boolean);
|
||||
constructor FloatColumn.Create(name: string; data: array of real; valid: array of boolean);
|
||||
begin
|
||||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctFloat);
|
||||
|
||||
Data := data;
|
||||
var n := Length(data);
|
||||
Data := if n = 0 then [] else data;
|
||||
|
||||
if valid = nil then
|
||||
IsValid := [True] * n
|
||||
else
|
||||
begin
|
||||
if Length(valid) <> n then
|
||||
Error(ER_INVALID_ISVALID_LENGTH);
|
||||
|
||||
IsValid := valid;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor FloatColumn.Create(name: string);
|
||||
begin
|
||||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctFloat);
|
||||
Data := new real[0];
|
||||
IsValid := nil;
|
||||
end;
|
||||
|
||||
Data := [];
|
||||
IsValid := [];
|
||||
end;
|
||||
|
||||
function FloatColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
||||
begin
|
||||
if (IsValid <> nil) and not IsValid[i] then
|
||||
exit(false);
|
||||
if not IsValid[i] then
|
||||
exit(False);
|
||||
|
||||
value := Data[i];
|
||||
exit(true);
|
||||
exit(True);
|
||||
end;
|
||||
|
||||
constructor StrColumn.Create(name: string; data: array of string;
|
||||
valid: array of boolean);
|
||||
constructor StrColumn.Create(name: string; data: array of string; valid: array of boolean);
|
||||
begin
|
||||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctStr);
|
||||
|
||||
Data := data;
|
||||
var n := Length(data);
|
||||
Data := if n = 0 then [] else data;
|
||||
|
||||
if valid = nil then
|
||||
IsValid := [True] * n
|
||||
else
|
||||
begin
|
||||
if Length(valid) <> n then
|
||||
Error(ER_INVALID_ISVALID_LENGTH);
|
||||
|
||||
IsValid := valid;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor StrColumn.Create(name: string);
|
||||
begin
|
||||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctStr);
|
||||
|
||||
Data := new string[0];
|
||||
IsValid := nil;
|
||||
Data := [];
|
||||
IsValid := [];
|
||||
end;
|
||||
|
||||
function StrColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
||||
begin
|
||||
exit(false);
|
||||
exit(False);
|
||||
end;
|
||||
|
||||
function BoolColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
||||
begin
|
||||
if (IsValid <> nil) and not IsValid[i] then
|
||||
exit(false);
|
||||
|
||||
if Data[i] then
|
||||
value := 1.0
|
||||
else
|
||||
value := 0.0;
|
||||
|
||||
exit(true);
|
||||
end;
|
||||
|
||||
constructor BoolColumn.Create(name: string; data: array of boolean;
|
||||
valid: array of boolean);
|
||||
constructor BoolColumn.Create(name: string; data: array of boolean; valid: array of boolean);
|
||||
begin
|
||||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctBool);
|
||||
|
||||
Data := data;
|
||||
var n := Length(data);
|
||||
Data := if n = 0 then [] else data;
|
||||
|
||||
if valid = nil then
|
||||
IsValid := [True] * n
|
||||
else
|
||||
begin
|
||||
if Length(valid) <> n then
|
||||
Error(ER_INVALID_ISVALID_LENGTH);
|
||||
|
||||
IsValid := valid;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor BoolColumn.Create(name: string);
|
||||
begin
|
||||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctBool);
|
||||
|
||||
Data := new boolean[0];
|
||||
IsValid := nil;
|
||||
Data := [];
|
||||
IsValid := [];
|
||||
end;
|
||||
|
||||
{procedure BoolColumn.AppendFromCursor(cur: DataFrameCursor; colIndex: integer);
|
||||
function BoolColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
||||
begin
|
||||
if cur.IsValid(colIndex) then
|
||||
begin
|
||||
Data := Data + [cur.Bool(colIndex)];
|
||||
if IsValid <> nil then
|
||||
IsValid := IsValid + [true];
|
||||
end
|
||||
else AppendInvalid;
|
||||
end;}
|
||||
if not IsValid[i] then
|
||||
exit(False);
|
||||
|
||||
{procedure BoolColumn.AppendInvalid;
|
||||
begin
|
||||
Data := Data + [false];
|
||||
if Data[i] then
|
||||
value := 1.0
|
||||
else
|
||||
value := 0.0;
|
||||
|
||||
if IsValid = nil then
|
||||
begin
|
||||
IsValid := new boolean[Length(Data) - 1];
|
||||
for var i := 0 to IsValid.Length - 1 do
|
||||
IsValid[i] := true;
|
||||
exit(True);
|
||||
end;
|
||||
|
||||
IsValid := IsValid + [false];
|
||||
end;}
|
||||
|
||||
|
||||
//-----------------------------
|
||||
// JoinKey
|
||||
|
|
@ -772,9 +802,6 @@ begin
|
|||
ctInt:
|
||||
begin
|
||||
var c := IntColumn(col);
|
||||
if c.IsValid = nil then
|
||||
validAcc[i] := pos -> true
|
||||
else
|
||||
validAcc[i] := pos -> c.IsValid[pos];
|
||||
|
||||
intAcc[i] := pos -> c.Data[pos];
|
||||
|
|
@ -784,9 +811,6 @@ begin
|
|||
ctFloat:
|
||||
begin
|
||||
var c := FloatColumn(col);
|
||||
if c.IsValid = nil then
|
||||
validAcc[i] := pos -> true
|
||||
else
|
||||
validAcc[i] := pos -> c.IsValid[pos];
|
||||
|
||||
floatAcc[i] := pos -> c.Data[pos];
|
||||
|
|
@ -796,9 +820,6 @@ begin
|
|||
ctStr:
|
||||
begin
|
||||
var c := StrColumn(col);
|
||||
if c.IsValid = nil then
|
||||
validAcc[i] := pos -> true
|
||||
else
|
||||
validAcc[i] := pos -> c.IsValid[pos];
|
||||
|
||||
strAcc[i] := pos -> c.Data[pos];
|
||||
|
|
@ -807,9 +828,6 @@ begin
|
|||
ctBool:
|
||||
begin
|
||||
var c := BoolColumn(col);
|
||||
if c.IsValid = nil then
|
||||
validAcc[i] := pos -> true
|
||||
else
|
||||
validAcc[i] := pos -> c.IsValid[pos];
|
||||
|
||||
boolAcc[i] := pos -> c.Data[pos];
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
/// Линейная алгебра для алгоритмов машинного обучения.
|
||||
// =============================================================
|
||||
// СТАТИСТИЧЕСКОЕ СОГЛАШЕНИЕ (LinearAlgebraML)
|
||||
//
|
||||
// Используется дисперсия генеральной совокупности (деление на n),
|
||||
// как принято в численных методах и алгоритмах машинного обучения.
|
||||
//
|
||||
// См. статистическую политику в модуле MLABC.
|
||||
// =============================================================
|
||||
|
||||
/// Линейная алгебра для алгоритмов машинного обучения.
|
||||
///
|
||||
/// Содержит типы Vector и Matrix и численные методы,
|
||||
/// используемые в моделях ML:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,23 @@
|
|||
/// Основной модуль библиотеки машинного обучения.
|
||||
// =============================================================
|
||||
// СТАТИСТИЧЕСКАЯ ПОЛИТИКА БИБЛИОТЕКИ ML PascalABC.NET
|
||||
//
|
||||
// В библиотеке используются следующие соглашения:
|
||||
//
|
||||
// 1. DataFrame (описательная статистика):
|
||||
// • дисперсия вычисляется с делением на (n - 1)
|
||||
//
|
||||
// 2. LinearAlgebra и ML:
|
||||
// • дисперсия вычисляется с делением на n
|
||||
//
|
||||
// 3. PCA:
|
||||
// • ковариационная матрица вычисляется с делением на (n - 1)
|
||||
//
|
||||
// Это соответствует распространённой практике:
|
||||
// • описательная статистика — выборочная дисперсия
|
||||
// • алгоритмы ML — дисперсия генеральной совокупности
|
||||
// =============================================================
|
||||
|
||||
/// Основной модуль библиотеки машинного обучения.
|
||||
/// Объединяет модели, метрики, валидацию и вспомогательные компоненты.
|
||||
unit MLABC;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -8,6 +8,24 @@ interface
|
|||
|
||||
uses LinearAlgebraML;
|
||||
|
||||
/// Определяет фактический seed для генератора случайных чисел.
|
||||
///
|
||||
/// Если seed >= 0:
|
||||
/// • используется заданное пользователем значение
|
||||
/// • userProvided := true
|
||||
///
|
||||
/// Если seed < 0:
|
||||
/// • генерируется псевдослучайный seed на основе системного времени
|
||||
/// • userProvided := false
|
||||
///
|
||||
/// Возвращает:
|
||||
/// • неотрицательный seed, используемый для инициализации RNG
|
||||
///
|
||||
/// Назначение:
|
||||
/// • обеспечить единое поведение случайности во всех моделях
|
||||
/// • сохранить воспроизводимость при явном задании seed
|
||||
function ResolveRandomSeed(seed: integer; var userProvided: boolean): integer;
|
||||
|
||||
/// Преобразует вектор меток классов в массив целых чисел.
|
||||
/// Используется при визуализации и других задачах,
|
||||
/// где метки должны быть представлены как 0,1,2,...
|
||||
|
|
@ -70,6 +88,20 @@ const
|
|||
'Индекс метки {0} вне диапазона [0, {1})!!Label index {0} is out of range [0, {1})';
|
||||
|
||||
|
||||
function ResolveRandomSeed(seed: integer; var userProvided: boolean): integer;
|
||||
begin
|
||||
if seed < 0 then
|
||||
begin
|
||||
userProvided := false;
|
||||
Result := System.Environment.TickCount and integer.MaxValue;
|
||||
end
|
||||
else
|
||||
begin
|
||||
userProvided := true;
|
||||
Result := seed;
|
||||
end;
|
||||
end;
|
||||
|
||||
function LabelsToInts(y: Vector): array of integer;
|
||||
begin
|
||||
if y = nil then
|
||||
|
|
|
|||
|
|
@ -53,11 +53,18 @@ type
|
|||
/// Создаёт LabelEncoder для указанного столбца
|
||||
constructor Create(column: string);
|
||||
|
||||
/// Определяет множество категорий и сохраняет их коды
|
||||
/// Определяет множество категорий столбца и сохраняет их числовое кодирование.
|
||||
/// df — таблица данных.
|
||||
/// Сохраняет отображение категорий в числовые коды для последующего применения.
|
||||
///
|
||||
/// Примечание:
|
||||
/// • отображение категорий НЕ копируется методом Clone
|
||||
function Fit(df: DataFrame): IPreprocessor;
|
||||
|
||||
/// Заменяет категории их числовыми кодами
|
||||
/// Возвращает новый DataFrame
|
||||
function Transform(df: DataFrame): DataFrame;
|
||||
|
||||
/// Выполняет Fit и Transform последовательно
|
||||
function FitTransform(df: DataFrame): DataFrame;
|
||||
|
||||
|
|
@ -65,6 +72,15 @@ type
|
|||
|
||||
property ColumnName: string read col;
|
||||
|
||||
/// Создаёт копию препроцессора с той же конфигурацией.
|
||||
///
|
||||
/// ВАЖНО:
|
||||
/// • Clone копирует только конфигурацию (например, имя столбца)
|
||||
/// • Clone НЕ копирует обученное состояние (mapping, статистики и т.п.)
|
||||
///
|
||||
/// Назначение:
|
||||
/// • использование в Pipeline и CrossValidate
|
||||
/// • обеспечивает независимое переобучение препроцессоров
|
||||
function Clone: IPreprocessor;
|
||||
end;
|
||||
|
||||
|
|
@ -82,8 +98,14 @@ type
|
|||
/// Создаёт OneHotEncoder для указанного столбца
|
||||
constructor Create(column: string);
|
||||
|
||||
/// Определяет множество категорий столбца
|
||||
/// Определяет множество категорий столбца.
|
||||
/// df — таблица данных.
|
||||
/// Сохраняет категории для последующего преобразования в one-hot представление.
|
||||
///
|
||||
/// Примечание:
|
||||
/// • категории НЕ копируются методом Clone
|
||||
function Fit(df: DataFrame): IPreprocessor;
|
||||
|
||||
/// Заменяет столбец набором бинарных столбцов
|
||||
/// Возвращает новый DataFrame
|
||||
function Transform(df: DataFrame): DataFrame;
|
||||
|
|
@ -94,6 +116,15 @@ type
|
|||
|
||||
property ColumnName: string read col;
|
||||
|
||||
/// Создаёт копию препроцессора с той же конфигурацией.
|
||||
///
|
||||
/// ВАЖНО:
|
||||
/// • Clone копирует только конфигурацию (например, имя столбца)
|
||||
/// • Clone НЕ копирует обученное состояние (mapping, статистики и т.п.)
|
||||
///
|
||||
/// Назначение:
|
||||
/// • использование в Pipeline и CrossValidate
|
||||
/// • обеспечивает независимое переобучение препроцессоров
|
||||
function Clone: IPreprocessor;
|
||||
end;
|
||||
|
||||
|
|
@ -118,11 +149,19 @@ type
|
|||
/// Создаёт Imputer с константной стратегией заполнения
|
||||
constructor Create(value: object; params columns: array of string);
|
||||
|
||||
/// Вычисляет значения для заполнения пропусков
|
||||
/// Вычисляет значения для заполнения пропусков.
|
||||
/// df — таблица данных.
|
||||
/// В зависимости от стратегии вычисляет параметры заполнения
|
||||
/// (например, среднее, медиану или константу) для каждого столбца.
|
||||
///
|
||||
/// Примечание:
|
||||
/// • вычисленные параметры НЕ копируются методом Clone
|
||||
function Fit(df: DataFrame): IPreprocessor;
|
||||
|
||||
/// Заполняет пропущенные значения в DataFrame
|
||||
/// Возвращает новый DataFrame
|
||||
function Transform(df: DataFrame): DataFrame;
|
||||
|
||||
/// Выполняет Fit и Transform последовательно
|
||||
function FitTransform(df: DataFrame): DataFrame;
|
||||
|
||||
|
|
@ -130,6 +169,15 @@ type
|
|||
|
||||
property Columns: array of string read cols;
|
||||
|
||||
/// Создаёт копию препроцессора с той же конфигурацией.
|
||||
///
|
||||
/// ВАЖНО:
|
||||
/// • Clone копирует только конфигурацию (например, имя столбца)
|
||||
/// • Clone НЕ копирует обученное состояние (mapping, статистики и т.п.)
|
||||
///
|
||||
/// Назначение:
|
||||
/// • использование в Pipeline и CrossValidate
|
||||
/// • обеспечивает независимое переобучение препроцессоров
|
||||
function Clone: IPreprocessor;
|
||||
end;
|
||||
|
||||
|
|
@ -262,7 +310,7 @@ begin
|
|||
var n := df.RowCount;
|
||||
|
||||
var data := new integer[n];
|
||||
var valid: array of boolean := nil;
|
||||
var valid := new boolean[n];
|
||||
|
||||
var cur := df.GetCursor;
|
||||
var row := 0;
|
||||
|
|
@ -270,13 +318,7 @@ begin
|
|||
begin
|
||||
if not cur.IsValid(idx) then
|
||||
begin
|
||||
if valid = nil then
|
||||
begin
|
||||
valid := new boolean[n];
|
||||
for var j := 0 to row - 1 do
|
||||
valid[j] := true;
|
||||
end;
|
||||
valid[row] := false;
|
||||
valid[row] := False;
|
||||
data[row] := 0;
|
||||
end
|
||||
else
|
||||
|
|
@ -287,8 +329,7 @@ begin
|
|||
Error(ER_LABELENCODER_UNSEEN_CATEGORY, s);
|
||||
|
||||
data[row] := mapping[s];
|
||||
if valid <> nil then
|
||||
valid[row] := true;
|
||||
valid[row] := True;
|
||||
end;
|
||||
|
||||
row += 1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue