dataframe.concat сделан
This commit is contained in:
parent
3938120846
commit
490d539df3
|
|
@ -15,7 +15,7 @@ internal static class RevisionClass
|
|||
public const string Major = "3";
|
||||
public const string Minor = "11";
|
||||
public const string Build = "1";
|
||||
public const string Revision = "3828";
|
||||
public const string Revision = "3830";
|
||||
|
||||
public const string MainVersion = Major + "." + Minor;
|
||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%COREVERSION%=1
|
||||
%REVISION%=3828
|
||||
%REVISION%=3830
|
||||
%MINOR%=11
|
||||
%MAJOR%=3
|
||||
|
|
|
|||
18
InstallerSamples/MachineLearning/02_DataFrame/df22.pas
Normal file
18
InstallerSamples/MachineLearning/02_DataFrame/df22.pas
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
uses DataFrameABC;
|
||||
|
||||
begin
|
||||
var df1 := DataFrame.FromCsvText('''
|
||||
id,name,age
|
||||
1,Ann,10
|
||||
2,Bob,12
|
||||
''');
|
||||
|
||||
var df2 := DataFrame.FromCsvText('''
|
||||
id,name,age
|
||||
3,Cat,11
|
||||
4,Dan,13
|
||||
''');
|
||||
|
||||
var df := DataFrame.Concat(df1, df2);
|
||||
df.Print;
|
||||
end.
|
||||
|
|
@ -1 +1 @@
|
|||
3.11.1.3828
|
||||
3.11.1.3830
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
!define VERSION '3.11.1.3828'
|
||||
!define VERSION '3.11.1.3830'
|
||||
|
|
|
|||
|
|
@ -370,6 +370,12 @@ type
|
|||
function Join(other: DataFrame; keys: array of string; kind: JoinKind := jkInner): DataFrame;
|
||||
/// Соединяет с другим DataFrame по разным именам ключей
|
||||
function Join(other: DataFrame; leftKeys, rightKeys: array of string; kind: JoinKind := jkInner): DataFrame;
|
||||
|
||||
/// Склеивает несколько DataFrame по строкам.
|
||||
/// Все таблицы должны иметь одинаковую схему:
|
||||
/// имена столбцов, их порядок, типы и categorical-флаги должны совпадать.
|
||||
/// Возвращает новый DataFrame.
|
||||
static function Concat(params dfs: array of DataFrame): DataFrame;
|
||||
|
||||
/// Выводит DataFrame с настраиваемым числом строк
|
||||
procedure Print(maxRows: integer := 10; headRows: integer := -1; decimals: integer := 2);
|
||||
|
|
@ -618,6 +624,13 @@ const
|
|||
'CSV format error: expected {0} columns, got {1}';
|
||||
ER_EMPTY_CSV =
|
||||
'CSV-файл пуст!!Empty CSV';
|
||||
ER_CONCAT_EMPTY =
|
||||
'DataFrame.Concat требует хотя бы один DataFrame!!DataFrame.Concat requires at least one DataFrame';
|
||||
ER_CONCAT_DF_NULL =
|
||||
'DataFrame.Concat не принимает nil-таблицы!!DataFrame.Concat does not accept nil dataframes';
|
||||
ER_CONCAT_SCHEMA_MISMATCH =
|
||||
'DataFrame.Concat требует одинаковую схему: имена, порядок, типы и categorical-флаги столбцов должны совпадать!!' +
|
||||
'DataFrame.Concat requires identical schema: column names, order, types, and categorical flags must match';
|
||||
ER_CSV_UNCLOSED_QUOTE =
|
||||
'Ошибка формата CSV: незакрытая кавычка!!CSV format error: unclosed quote';
|
||||
ER_CSV_INVALID_BOOL =
|
||||
|
|
@ -4455,6 +4468,129 @@ begin
|
|||
Result := CsvLoader.LoadFromLines(text.ToLines);
|
||||
end;
|
||||
|
||||
static function DataFrame.Concat(params dfs: array of DataFrame): DataFrame;
|
||||
begin
|
||||
if (dfs = nil) or (dfs.Length = 0) then
|
||||
ArgumentError(ER_CONCAT_EMPTY);
|
||||
|
||||
for var i := 0 to dfs.Length - 1 do
|
||||
if dfs[i] = nil then
|
||||
ArgumentError(ER_CONCAT_DF_NULL);
|
||||
|
||||
var first := dfs[0];
|
||||
var schema := first.fSchema;
|
||||
|
||||
for var di := 1 to dfs.Length - 1 do
|
||||
begin
|
||||
var curSchema := dfs[di].fSchema;
|
||||
|
||||
if curSchema.ColumnCount <> schema.ColumnCount then
|
||||
ArgumentError(ER_CONCAT_SCHEMA_MISMATCH);
|
||||
|
||||
for var ci := 0 to schema.ColumnCount - 1 do
|
||||
if (curSchema.NameAt(ci) <> schema.NameAt(ci)) or
|
||||
(curSchema.ColumnTypeAt(ci) <> schema.ColumnTypeAt(ci)) or
|
||||
(curSchema.IsCategoricalAt(ci) <> schema.IsCategoricalAt(ci)) then
|
||||
ArgumentError(ER_CONCAT_SCHEMA_MISMATCH);
|
||||
end;
|
||||
|
||||
var totalRows := 0;
|
||||
for var di := 0 to dfs.Length - 1 do
|
||||
totalRows += dfs[di].RowCount;
|
||||
|
||||
var res := new DataFrame;
|
||||
|
||||
for var ci := 0 to schema.ColumnCount - 1 do
|
||||
begin
|
||||
var name := schema.NameAt(ci);
|
||||
|
||||
case schema.ColumnTypeAt(ci) of
|
||||
ctInt:
|
||||
begin
|
||||
var data := new integer[totalRows];
|
||||
var valid := new boolean[totalRows];
|
||||
var pos := 0;
|
||||
|
||||
for var di := 0 to dfs.Length - 1 do
|
||||
begin
|
||||
var col := IntColumn(dfs[di].columns[ci]);
|
||||
for var r := 0 to col.Data.Length - 1 do
|
||||
begin
|
||||
data[pos] := col.Data[r];
|
||||
valid[pos] := col.IsValid[r];
|
||||
pos += 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
res.AddIntColumn(name, data, valid);
|
||||
end;
|
||||
|
||||
ctFloat:
|
||||
begin
|
||||
var data := new real[totalRows];
|
||||
var valid := new boolean[totalRows];
|
||||
var pos := 0;
|
||||
|
||||
for var di := 0 to dfs.Length - 1 do
|
||||
begin
|
||||
var col := FloatColumn(dfs[di].columns[ci]);
|
||||
for var r := 0 to col.Data.Length - 1 do
|
||||
begin
|
||||
data[pos] := col.Data[r];
|
||||
valid[pos] := col.IsValid[r];
|
||||
pos += 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
res.AddFloatColumn(name, data, valid);
|
||||
end;
|
||||
|
||||
ctStr:
|
||||
begin
|
||||
var data := new string[totalRows];
|
||||
var valid := new boolean[totalRows];
|
||||
var pos := 0;
|
||||
|
||||
for var di := 0 to dfs.Length - 1 do
|
||||
begin
|
||||
var col := StrColumn(dfs[di].columns[ci]);
|
||||
for var r := 0 to col.Data.Length - 1 do
|
||||
begin
|
||||
data[pos] := col.Data[r];
|
||||
valid[pos] := col.IsValid[r];
|
||||
pos += 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
res.AddStrColumn(name, data, valid);
|
||||
end;
|
||||
|
||||
ctBool:
|
||||
begin
|
||||
var data := new boolean[totalRows];
|
||||
var valid := new boolean[totalRows];
|
||||
var pos := 0;
|
||||
|
||||
for var di := 0 to dfs.Length - 1 do
|
||||
begin
|
||||
var col := BoolColumn(dfs[di].columns[ci]);
|
||||
for var r := 0 to col.Data.Length - 1 do
|
||||
begin
|
||||
data[pos] := col.Data[r];
|
||||
valid[pos] := col.IsValid[r];
|
||||
pos += 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
res.AddBoolColumn(name, data, valid);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
res.SetSchema(schema);
|
||||
Result := res;
|
||||
end;
|
||||
|
||||
procedure DataFrame.ToCsv(filename: string);
|
||||
begin
|
||||
CsvSaver.Save(self, filename, ',', true);
|
||||
|
|
|
|||
|
|
@ -44,18 +44,29 @@ unit MLABC;
|
|||
// ПОЛИТИКА PREDICT
|
||||
//
|
||||
// 1. Классификация:
|
||||
// • Predict возвращает метки классов в том же виде,
|
||||
// в каком они были поданы модели при обучении.
|
||||
// • Для матричных моделей Predict возвращает метки классов
|
||||
// в том виде, в каком они были поданы модели при обучении.
|
||||
//
|
||||
// • ClassificationMatrixPipeline следует той же политике:
|
||||
// Predict возвращает метки классов в том виде,
|
||||
// в каком они были поданы вложенной модели при обучении.
|
||||
//
|
||||
// • ClassificationDataPipeline работает с DataFrame, где целевой столбец
|
||||
// часто является строковым. Поэтому внутри pipeline целевой столбец
|
||||
// кодируется в целые числа, и Predict возвращает именно эти коды.
|
||||
//
|
||||
// • PredictLabels возвращает строковые метки классов.
|
||||
//
|
||||
// • Таким образом, различие естественно:
|
||||
// матричные модели и ClassificationMatrixPipeline возвращают метки
|
||||
// из пространства обучения модели, а ClassificationDataPipeline
|
||||
// возвращает коды, построенные при кодировании целевого столбца.
|
||||
//
|
||||
// 2. Регрессия:
|
||||
// • Predict возвращает вектор числовых предсказаний.
|
||||
//
|
||||
// 3. Кластеризация:
|
||||
// • Predict и FitPredict возвращают номера кластеров.
|
||||
//
|
||||
// Внутреннее кодирование классов может использоваться внутри модели,
|
||||
// но наружу через Predict оно не выдаётся.
|
||||
// =============================================================
|
||||
|
||||
interface
|
||||
|
|
|
|||
|
|
@ -7116,6 +7116,9 @@ function GradientBoostingClassifier.PredictStage(X: Matrix; m: integer): array o
|
|||
begin
|
||||
var probs := PredictStageProba(X, m);
|
||||
|
||||
if fLabels = nil then
|
||||
ArgumentError(ER_CLASSES_NOT_AVAILABLE);
|
||||
|
||||
var n := probs.RowCount;
|
||||
SetLength(Result, n);
|
||||
|
||||
|
|
@ -7131,7 +7134,7 @@ begin
|
|||
best := cls;
|
||||
end;
|
||||
|
||||
Result[i] := fClasses[best];
|
||||
Result[i] := fLabels.ClassValueAt(best);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
|
|||
|
|
@ -879,21 +879,23 @@ end;
|
|||
|
||||
function ClassificationDataPipeline.PredictLabels(df: DataFrame): array of string;
|
||||
begin
|
||||
if df = nil then
|
||||
ArgumentNullError(ER_ARG_NULL, 'df');
|
||||
if not fFitted then
|
||||
NotFittedError(ER_FIT_NOT_CALLED);
|
||||
|
||||
var encoded := Predict(df);
|
||||
var classes := GetClassLabels;
|
||||
Result := new string[encoded.Length];
|
||||
|
||||
for var i := 0 to encoded.Length - 1 do
|
||||
begin
|
||||
var idx := encoded[i];
|
||||
if (idx < 0) or (idx >= classes.Length) then
|
||||
Error(ER_LABEL_INDEX_OUT_OF_RANGE, idx, classes.Length);
|
||||
|
||||
Result[i] := classes[idx];
|
||||
end;
|
||||
if fModel = nil then
|
||||
ArgumentError(ER_MODEL_NULL);
|
||||
|
||||
if not (fModel is IClassifier) then
|
||||
Error(ER_PREDICT_NOT_SUPPORTED);
|
||||
|
||||
var current := Transform(df);
|
||||
|
||||
var X := current.ToMatrix(fFinalFeatures);
|
||||
X := TransformMatrix(X);
|
||||
|
||||
Result := (fModel as IClassifier).PredictLabels(X);
|
||||
end;
|
||||
|
||||
function ClassificationDataPipeline.PredictProba(df: DataFrame): Matrix;
|
||||
|
|
|
|||
Loading…
Reference in a new issue