"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __commonJS = (cb, mod) => function __require() {
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => {
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
  return value;
};

// node_modules/stemmer/index.js
var require_stemmer = __commonJS({
  "node_modules/stemmer/index.js"(exports, module2) {
    "use strict";
    module2.exports = stemmer2;
    var step2list = {
      ational: "ate",
      tional: "tion",
      enci: "ence",
      anci: "ance",
      izer: "ize",
      bli: "ble",
      alli: "al",
      entli: "ent",
      eli: "e",
      ousli: "ous",
      ization: "ize",
      ation: "ate",
      ator: "ate",
      alism: "al",
      iveness: "ive",
      fulness: "ful",
      ousness: "ous",
      aliti: "al",
      iviti: "ive",
      biliti: "ble",
      logi: "log"
    };
    var step3list = {
      icate: "ic",
      ative: "",
      alize: "al",
      iciti: "ic",
      ical: "ic",
      ful: "",
      ness: ""
    };
    var consonant = "[^aeiou]";
    var vowel = "[aeiouy]";
    var consonants = "(" + consonant + "[^aeiouy]*)";
    var vowels = "(" + vowel + "[aeiou]*)";
    var gt0 = new RegExp("^" + consonants + "?" + vowels + consonants);
    var eq1 = new RegExp("^" + consonants + "?" + vowels + consonants + vowels + "?$");
    var gt1 = new RegExp("^" + consonants + "?(" + vowels + consonants + "){2,}");
    var vowelInStem = new RegExp("^" + consonants + "?" + vowel);
    var consonantLike = new RegExp("^" + consonants + vowel + "[^aeiouwxy]$");
    var sfxLl = /ll$/;
    var sfxE = /^(.+?)e$/;
    var sfxY = /^(.+?)y$/;
    var sfxIon = /^(.+?(s|t))(ion)$/;
    var sfxEdOrIng = /^(.+?)(ed|ing)$/;
    var sfxAtOrBlOrIz = /(at|bl|iz)$/;
    var sfxEED = /^(.+?)eed$/;
    var sfxS = /^.+?[^s]s$/;
    var sfxSsesOrIes = /^.+?(ss|i)es$/;
    var sfxMultiConsonantLike = /([^aeiouylsz])\1$/;
    var step2 = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
    var step3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
    var step4 = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
    function stemmer2(value) {
      var firstCharacterWasLowerCaseY;
      var match;
      value = String(value).toLowerCase();
      if (value.length < 3) {
        return value;
      }
      if (value.charCodeAt(0) === 121) {
        firstCharacterWasLowerCaseY = true;
        value = "Y" + value.slice(1);
      }
      if (sfxSsesOrIes.test(value)) {
        value = value.slice(0, value.length - 2);
      } else if (sfxS.test(value)) {
        value = value.slice(0, value.length - 1);
      }
      if (match = sfxEED.exec(value)) {
        if (gt0.test(match[1])) {
          value = value.slice(0, value.length - 1);
        }
      } else if ((match = sfxEdOrIng.exec(value)) && vowelInStem.test(match[1])) {
        value = match[1];
        if (sfxAtOrBlOrIz.test(value)) {
          value += "e";
        } else if (sfxMultiConsonantLike.test(value)) {
          value = value.slice(0, value.length - 1);
        } else if (consonantLike.test(value)) {
          value += "e";
        }
      }
      if ((match = sfxY.exec(value)) && vowelInStem.test(match[1])) {
        value = match[1] + "i";
      }
      if ((match = step2.exec(value)) && gt0.test(match[1])) {
        value = match[1] + step2list[match[2]];
      }
      if ((match = step3.exec(value)) && gt0.test(match[1])) {
        value = match[1] + step3list[match[2]];
      }
      if (match = step4.exec(value)) {
        if (gt1.test(match[1])) {
          value = match[1];
        }
      } else if ((match = sfxIon.exec(value)) && gt1.test(match[1])) {
        value = match[1];
      }
      if ((match = sfxE.exec(value)) && (gt1.test(match[1]) || eq1.test(match[1]) && !consonantLike.test(match[1]))) {
        value = match[1];
      }
      if (sfxLl.test(value) && gt1.test(value)) {
        value = value.slice(0, value.length - 1);
      }
      if (firstCharacterWasLowerCaseY) {
        value = "y" + value.slice(1);
      }
      return value;
    }
  }
});

// src/index.ts
var src_exports = {};
__export(src_exports, {
  DataSet: () => DataSet,
  PD: () => import_probability_distributions.default,
  calc: () => calc,
  cross_validation: () => cross_validation,
  csv: () => csv2,
  nlp: () => nlp,
  util: () => util
});
module.exports = __toCommonJS(src_exports);

// src/csv.ts
var csv_exports = {};
__export(csv_exports, {
  loadCSV: () => loadCSV,
  loadCSVURI: () => loadCSVURI,
  loadTSV: () => loadTSV
});
var import_http = require("http");
var import_https = require("https");
var import_valid_url = __toESM(require("valid-url"), 1);
var import_csvtojson = __toESM(require("csvtojson"), 1);
async function loadCSVURI(filepath, options) {
  const reqMethod = filepath.search(/https/gi) > -1 ? import_https.get : import_http.get;
  return new Promise((resolve, reject) => {
    const csvData = [];
    const config = Object.assign({ checkType: true }, options);
    const req = reqMethod(filepath, (res) => {
      (0, import_csvtojson.default)(config).fromStream(res).subscribe((json) => {
        csvData.push(json);
      }, (err) => {
        return reject(err);
      }, (error) => {
        if (error) {
          return reject(error);
        } else {
          return resolve(csvData);
        }
      });
    });
    req.on("error", reject);
  });
}
async function loadCSV(filepath, options) {
  if (import_valid_url.default.isUri(filepath)) {
    return loadCSVURI(filepath, options);
  } else {
    return new Promise((resolve, reject) => {
      const csvData = [];
      const config = Object.assign({ checkType: true }, options);
      (0, import_csvtojson.default)(config).fromFile(filepath).subscribe((json, lineNumber) => {
        csvData.push(json);
      }, (err) => {
        return reject(err);
      }, (error) => {
        if (error) {
          return reject(error);
        } else {
          return resolve(csvData);
        }
      });
    });
  }
}
async function loadTSV(filepath, options) {
  const tsvOptions = Object.assign({
    checkType: true
  }, options, {
    delimiter: "	"
  });
  return loadCSV(filepath, tsvOptions);
}

// src/index.ts
var import_probability_distributions = __toESM(require("probability-distributions"), 1);

// src/stub.ts
var import_stemmer = __toESM(require_stemmer(), 1);
var natural = {
  PorterStemmer: {
    tokenizeAndStem: (input = "") => {
      const stems = input.split(" ").map((word) => word.trim()).filter((word) => word).map(import_stemmer.default);
      return stems;
    }
  }
};
var stub_default = natural;

// src/DataSet.ts
var import_ml_stat2 = require("ml-stat");

// src/util.ts
var import_ml_stat = require("ml-stat");
var import_lodash = __toESM(require("lodash.range"), 1);
var import_lodash2 = __toESM(require("lodash.rangeright"), 1);
var avg = import_ml_stat.array.mean;
var mean = avg;
var sum = import_ml_stat.array.sum;
var scale = (a, d) => a.map((x) => (x - avg(a)) / d);
var max = import_ml_stat.array.max;
var min = import_ml_stat.array.min;
var sd = import_ml_stat.array.standardDeviation;
function squaredDifference(left, right) {
  return left.reduce((result, val, index, arr) => {
    result.push(Math.pow(right[index] - val, 2));
    return result;
  }, []);
}
function standardError(actuals = [], estimates = []) {
  if (actuals.length !== estimates.length)
    throw new RangeError("arrays must have the same length");
  const squaredDiff = squaredDifference(actuals, estimates);
  return Math.sqrt(sum(squaredDiff) / (actuals.length - 2));
}
function standardScore(observations = []) {
  const mean2 = avg(observations);
  const stdDev = sd(observations);
  return observations.map((x) => (x - mean2) / stdDev);
}
function coefficientOfDetermination(actuals = [], estimates = []) {
  if (actuals.length !== estimates.length)
    throw new RangeError("arrays must have the same length");
  const actualsMean = mean(actuals);
  const totalVariation = sum(actuals.reduce((result, val, index) => {
    result.push(Math.pow(actuals[index] - actualsMean, 2));
    return result;
  }, []));
  const unexplainedVariation = sum(actuals.reduce((result, val, index) => {
    result.push(Math.pow(actuals[index] - estimates[index], 2));
    return result;
  }, []));
  const rSquared2 = (totalVariation - unexplainedVariation) / totalVariation;
  return rSquared2;
}
function adjustedCoefficentOfDetermination(options) {
  const { actuals, estimates, rSquared: rSquared2, independentVariables, sampleSize } = options;
  const r2 = rSquared2 || coefficientOfDetermination(actuals, estimates);
  const n = sampleSize || actuals.length;
  const k = independentVariables;
  return 1 - (1 - r2) * ((n - 1) / (n - (k + 1)));
}
function coefficientOfCorrelation(actuals = [], estimates = []) {
  if (actuals.length !== estimates.length)
    throw new RangeError("arrays must have the same length");
  const sumX = sum(actuals);
  const sumY = sum(estimates);
  const sumProdXY = actuals.reduce((result, val, index) => {
    result = result + actuals[index] * estimates[index];
    return result;
  }, 0);
  const sumXSquared = actuals.reduce((result, val) => {
    result = result + val * val;
    return result;
  }, 0);
  const sumYSquared = estimates.reduce((result, val) => {
    result = result + val * val;
    return result;
  }, 0);
  const N = actuals.length;
  const R = (N * sumProdXY - sumX * sumY) / Math.sqrt((N * sumXSquared - Math.pow(sumX, 2)) * (N * sumYSquared - Math.pow(sumY, 2)));
  return R;
}
function rSquared(actuals = [], estimates = []) {
  return Math.pow(coefficientOfCorrelation(actuals, estimates), 2);
}
function pivotVector(vectors = []) {
  return vectors.reduce((result, val, index) => {
    val.forEach((vecVal, i) => {
      index === 0 ? result.push([vecVal]) : result[i].push(vecVal);
    });
    return result;
  }, []);
}
function pivotArrays(arrays = []) {
  return arrays.length ? arrays[0].map((vectorItem, index) => {
    const returnArray = [];
    arrays.forEach((v, i) => {
      returnArray.push(arrays[i][index]);
    });
    return returnArray;
  }) : arrays;
}
var StandardScaler = (z) => scale(z, sd(z));
function StandardScalerTransforms(vector = [], nan_value = -1, return_nan = false, inputComponents = {}) {
  const average = typeof inputComponents.average !== "undefined" ? inputComponents.average : avg(vector);
  const standard_dev = typeof inputComponents.standard_dev !== "undefined" ? inputComponents.standard_dev : sd(vector);
  const maximum = typeof inputComponents.maximum !== "undefined" ? inputComponents.maximum : max(vector);
  const minimum = typeof inputComponents.minimum !== "undefined" ? inputComponents.minimum : min(vector);
  const scale2 = (z) => {
    const scaledValue = (z - average) / standard_dev;
    if (isNaN(scaledValue) && return_nan)
      return scaledValue;
    else if (isNaN(scaledValue) && return_nan === false)
      return isNaN(standard_dev) ? z : standard_dev;
    else
      return scaledValue;
  };
  const descale = (scaledZ) => {
    const descaledValue = scaledZ * standard_dev + average;
    if (isNaN(descaledValue) && return_nan)
      return descaledValue;
    else if (isNaN(descaledValue) && return_nan === false)
      return isNaN(standard_dev) ? scaledZ : standard_dev;
    else
      return descaledValue;
  };
  const values = vector.map(scale2).map((val) => {
    if (isNaN(val))
      return nan_value;
    else
      return val;
  });
  return {
    components: {
      average,
      standard_dev,
      maximum,
      minimum
    },
    scale: scale2,
    descale,
    values
  };
}
var MinMaxScaler = (z) => scale(z, max(z) - min(z));
function MinMaxScalerTransforms(vector = [], nan_value = -1, return_nan = false, inputComponents = {}) {
  const average = typeof inputComponents.average !== "undefined" ? inputComponents.average : avg(vector);
  const standard_dev = typeof inputComponents.standard_dev !== "undefined" ? inputComponents.standard_dev : sd(vector);
  const maximum = typeof inputComponents.maximum !== "undefined" ? inputComponents.maximum : max(vector);
  const minimum = typeof inputComponents.minimum !== "undefined" ? inputComponents.minimum : min(vector);
  const scale2 = (z) => {
    const scaledValue = (z - average) / (maximum - minimum);
    if (isNaN(scaledValue) && return_nan)
      return scaledValue;
    else if (isNaN(scaledValue) && return_nan === false)
      return isNaN(standard_dev) ? z : standard_dev;
    else
      return scaledValue;
  };
  const descale = (scaledZ) => {
    const descaledValue = scaledZ * (maximum - minimum) + average;
    if (isNaN(descaledValue) && return_nan)
      return descaledValue;
    else if (isNaN(descaledValue) && return_nan === false)
      return isNaN(standard_dev) ? scaledZ : standard_dev;
    else
      return descaledValue;
  };
  const values = vector.map(scale2).map((val) => {
    if (isNaN(val))
      return nan_value;
    else
      return val;
  });
  return {
    components: {
      average,
      standard_dev,
      maximum,
      minimum
    },
    scale: scale2,
    descale,
    values
  };
}
function approximateZPercentile(z, alpha = true) {
  if (z < -6.5)
    return 0;
  if (z > 6.5)
    return 1;
  let factK = 1;
  let sum2 = 0;
  let term = 1;
  let k = 0;
  let loopStop = Math.exp(-23);
  while (Math.abs(term) > loopStop) {
    term = 0.3989422804 * Math.pow(-1, k) * Math.pow(z, k) / (2 * k + 1) / Math.pow(2, k) * Math.pow(z, k + 1) / factK;
    sum2 += term;
    k++;
    factK *= k;
  }
  sum2 += 0.5;
  return alpha ? 1 - sum2 : sum2;
}
function getSafePropertyName(name) {
  return name.replace(/[^\w\s]/gi, "_");
}
function forecastErrors(actuals, estimates) {
  if (actuals.length !== estimates.length)
    throw new Error(`Actuals length (${actuals.length}) must equal Estimates length (${estimates.length})`);
  return actuals.map((act, i) => act - estimates[i]);
}
function meanForecastError(actuals, estimates) {
  const errors = forecastErrors(actuals, estimates);
  return avg(errors);
}
function meanAbsoluteDeviation(actuals, estimates) {
  const errors = forecastErrors(actuals, estimates).map((e) => Math.abs(e));
  return avg(errors);
}
function trackingSignal(actuals, estimates) {
  const runningSumOfForecastErrors = sum(forecastErrors(actuals, estimates));
  const MAD = meanAbsoluteDeviation(actuals, estimates);
  return runningSumOfForecastErrors / MAD;
}
function meanSquaredError(actuals, estimates) {
  const squaredErrors = forecastErrors(actuals, estimates).map((e) => e * e);
  return avg(squaredErrors);
}
function MADMeanRatio(actuals, estimates) {
  const MAD = meanAbsoluteDeviation(actuals, estimates);
  const mean2 = avg(actuals);
  return MAD / mean2;
}
function meanAbsolutePercentageError(actuals, estimates) {
  const errors = forecastErrors(actuals, estimates).map((e) => Math.abs(e));
  const absErrorPercent = errors.map((e, i) => e / actuals[i]);
  return avg(absErrorPercent);
}
var util = {
  range: import_lodash.default,
  rangeRight: import_lodash2.default,
  scale,
  avg,
  mean: avg,
  sum,
  max,
  min,
  sd,
  StandardScaler,
  StandardScalerTransforms,
  MinMaxScaler,
  MinMaxScalerTransforms,
  LogScaler: (z) => z.map(Math.log),
  ExpScaler: (z) => z.map(Math.exp),
  squaredDifference,
  standardError,
  coefficientOfDetermination,
  coefficientOfCorrelation,
  r: coefficientOfCorrelation,
  rSquared,
  adjustedCoefficentOfDetermination,
  rBarSquared: adjustedCoefficentOfDetermination,
  adjustedRSquared: adjustedCoefficentOfDetermination,
  pivotVector,
  pivotArrays,
  standardScore,
  zScore: standardScore,
  approximateZPercentile,
  getSafePropertyName,
  forecastErrors,
  meanForecastError,
  MFE: meanForecastError,
  meanAbsoluteDeviation,
  MAD: meanAbsoluteDeviation,
  trackingSignal,
  TS: trackingSignal,
  meanSquaredError,
  MSE: meanSquaredError,
  MADMeanRatio,
  MMR: MADMeanRatio,
  meanAbsolutePercentageError,
  MAPE: meanAbsolutePercentageError
};

// src/DataSet.ts
var transformConfigMap = {
  scale: "scaleOptions",
  descale: "descaleOptions",
  label: "labelOptions",
  labelEncoder: "labelOptions",
  labeldecode: "labelOptions",
  labelDecode: "labelOptions",
  labelDecoder: "labelOptions",
  onehot: "oneHotOptions",
  oneHot: "oneHotOptions",
  oneHotEncode: "oneHotOptions",
  oneHotEncoder: "oneHotOptions",
  reducer: "reducerOptions",
  reduce: "reducerOptions",
  merge: "mergeData"
};
var _DataSet = class {
  config;
  data;
  labels;
  encoders;
  scalers;
  selectColumns;
  columnArray;
  encodeObject;
  oneHotEncoder;
  oneHotDecoder;
  columnMatrix;
  reverseColumnMatrix;
  reverseColumnVector;
  getTransforms;
  static getTransforms(transforms = {}) {
    return Object.keys(transforms).reduce((result, columnName) => {
      const transformColumnObject = transforms[columnName];
      const transformObject = {
        name: columnName,
        options: {
          strategy: Array.isArray(transformColumnObject) ? transformColumnObject[0] : transformColumnObject
        }
      };
      if (Array.isArray(transformColumnObject) && transformColumnObject.length > 1) {
        transformObject.options[transformConfigMap[transformColumnObject[0]]] = transformColumnObject[1];
      }
      result.push(transformObject);
      return result;
    }, []);
  }
  static reverseColumnMatrix(options = {}) {
    const { vectors = [], labels = [] } = options;
    const features = Array.isArray(labels) && Array.isArray(labels[0]) ? labels : labels.map((label) => [label]);
    return vectors.reduce((result, val) => {
      result.push(val.reduce((prop, value, index) => {
        prop[features[index][0]] = val[index];
        return prop;
      }, {}));
      return result;
    }, []);
  }
  static reverseColumnVector(options = {}) {
    const { vector = [], labels = [] } = options;
    const features = Array.isArray(labels) && Array.isArray(labels[0]) ? labels : labels.map((label) => [label]);
    return vector.reduce((result, val) => {
      result.push({ [features[0][0]]: val });
      return result;
    }, []);
  }
  static encodeObject(data, options) {
    const { labels, prefix, name } = options;
    const encodedData = labels.reduce((encodedObj, label) => {
      const oneHotLabelArrayName = `${prefix}${label}`;
      encodedObj[oneHotLabelArrayName] = label && data[name] && data[name].toString() === label.toString() ? 1 : 0;
      return encodedObj;
    }, {});
    return encodedData;
  }
  static oneHotEncoder(name, options) {
    const config = Object.assign({
      merge: true
    }, options);
    const labelData = config.data || this.columnArray(name, config.columnArrayOptions);
    const labels = Array.from(new Set(labelData).values());
    const prefix = config.prefix || `${name}_`;
    const encodedData = labelData.reduce((result, val, index, arr) => {
      labels.forEach((encodedLabel) => {
        const oneHotLabelArrayName = `${prefix}${encodedLabel}`;
        const oneHotVal = val === encodedLabel ? 1 : 0;
        if (Array.isArray(result[oneHotLabelArrayName])) {
          result[oneHotLabelArrayName].push(oneHotVal);
        } else {
          result[oneHotLabelArrayName] = [oneHotVal];
        }
      });
      return result;
    }, {});
    if (this.encoders.has(name) && config.merge) {
      this.encoders.get(name).labels = Array.from(new Set(labels.concat(this.encoders.get(name).labels)));
    } else {
      this.encoders.set(name, {
        name,
        labels,
        prefix
      });
    }
    return encodedData;
  }
  static oneHotDecoder(name, options) {
    const config = Object.assign({}, options);
    const encoderMap = config.encoders || this.encoders;
    const prefix = config.prefix || encoderMap.get(name).prefix;
    const labels = config.labels || encoderMap.get(name).labels;
    const encodedData = config.data || this.oneHotColumnArray(name, config.oneHotColumnArrayOptions);
    return encodedData.reduce((result, val) => {
      const columnNames = Object.keys(val).filter((prop) => val[prop] === 1 && (labels.indexOf(prop.replace(prefix, "")) !== -1 || labels.map((label) => String(label)).indexOf(prop.replace(prefix, "")) !== -1));
      const columnName = columnNames[0] || "";
      const datum = {
        [name]: columnName.replace(prefix, "")
      };
      result.push(datum);
      return result;
    }, []);
  }
  static oneHotColumnArray(name, oneHotColumnArrayOptions) {
    throw new Error("Method not implemented.");
  }
  static selectColumns(names, options = {}) {
    const config = Object.assign({}, options);
    const data = config.data || this.data;
    return data.reduce((result, val) => {
      const selectedData = {};
      names.forEach((name) => {
        selectedData[name] = val[name];
      });
      result.push(selectedData);
      return result;
    }, []);
  }
  static columnArray(name, options = {}) {
    const config = Object.assign({
      prefilter: () => true,
      filter: () => true,
      replace: {
        test: void 0,
        value: void 0
      },
      parseInt: false,
      parseIntBase: 10,
      parseFloat: options.scale ? true : false,
      scale: false
    }, options);
    const data = config.data || this.data;
    const modifiedColumn = data.filter(config.prefilter).reduce((result, val, index, arr) => {
      let objVal = val[name];
      let returnVal = typeof config.replace.test === "function" ? config.replace.test(objVal) ? typeof config.replace.value === "function" ? config.replace.value(result, val, index, arr, name) : config.replace.value : objVal : objVal;
      if (config.filter(returnVal)) {
        if (config.parseInt)
          result.push(parseInt(returnVal, config.parseIntBase));
        else if (config.parseFloat)
          result.push(parseFloat(returnVal));
        else
          result.push(returnVal);
      }
      return result;
    }, []);
    if (typeof config.scale === "function") {
      return modifiedColumn.map(config.scale);
    } else if (config.scale) {
      switch (config.scale) {
        case "standard":
          return util.StandardScaler(modifiedColumn);
        case "log":
          return util.LogScaler(modifiedColumn);
        case "exp":
          return util.ExpScaler(modifiedColumn);
        case "normalize":
        default:
          return util.MinMaxScaler(modifiedColumn);
      }
    } else {
      return modifiedColumn;
    }
  }
  static columnMatrix(vectors = [], data = []) {
    const options = data.length ? { data } : {};
    const columnVectors = Array.isArray(vectors) && Array.isArray(vectors[0]) ? vectors : vectors.map((vector) => [vector, options]);
    const vectorArrays = columnVectors.map((vec) => _DataSet.columnArray.call(this, ...vec));
    return util.pivotArrays(vectorArrays);
  }
  static mapToObject(mapObj = /* @__PURE__ */ new Map()) {
    return Array.from(mapObj.keys()).reduce((result, val) => {
      const mapVal = mapObj.get(val);
      if (mapVal instanceof Map) {
        result[val] = _DataSet.mapToObject(mapVal);
      } else if (typeof mapVal === "function") {
        result[val] = `[Function ${mapVal.name}]`;
      } else {
        result[val] = JSON.parse(JSON.stringify(mapVal));
      }
      return result;
    }, {});
  }
  static getBinaryValue(value = "") {
    if (!value)
      return 0;
    switch (value) {
      case false:
      case "N":
      case "n":
      case "NO":
      case "No":
      case "no":
      case "False":
      case "FALSE":
      case "F":
      case "f":
        return 0;
      default:
        return 1;
    }
  }
  constructor(data = [], options = {}) {
    this.config = Object.assign({
      debug: true
    }, options);
    this.data = [...data];
    this.labels = /* @__PURE__ */ new Map();
    this.encoders = /* @__PURE__ */ new Map();
    this.scalers = /* @__PURE__ */ new Map();
    this.selectColumns = _DataSet.selectColumns;
    this.columnArray = _DataSet.columnArray;
    this.encodeObject = _DataSet.encodeObject;
    this.oneHotEncoder = _DataSet.oneHotEncoder;
    this.oneHotDecoder = _DataSet.oneHotDecoder;
    this.columnMatrix = _DataSet.columnMatrix;
    this.reverseColumnMatrix = _DataSet.reverseColumnMatrix;
    this.reverseColumnVector = _DataSet.reverseColumnVector;
    this.getTransforms = _DataSet.getTransforms;
    if (this.config.labels || this.config.encoders || this.config.scalers) {
      this.importFeatures({
        labels: this.config.labels,
        encoders: this.config.encoders,
        scalers: this.config.scalers
      });
    }
    return this;
  }
  exportFeatures(options = {}) {
    const config = Object.assign({}, options);
    return {
      encoders: _DataSet.mapToObject(this.encoders),
      labels: _DataSet.mapToObject(this.labels),
      scalers: _DataSet.mapToObject(this.scalers)
    };
  }
  importFeatures(features = {}) {
    Object.keys(features.encoders || {}).forEach((encoderName) => {
      const encoder = features.encoders[encoderName];
      this.encoders.set(encoderName, encoder);
    });
    Object.keys(features.labels || {}).forEach((labelName) => {
      const labelData = features.labels[labelName];
      const labels = Object.keys(labelData).map((labelProp) => [labelProp, labelData[labelProp]]);
      if (typeof labelData["0"] !== "undefined" && typeof labelData["1"] !== "undefined") {
        labels.push(...[
          [0, false],
          [false, 0],
          [null, 0],
          ["no", 0],
          ["No", 0],
          ["NO", 0],
          ["FALSE", 0],
          ["F", 0],
          ["f", 0],
          ["null", 0],
          ["", 0],
          [void 0, 0],
          ["undefined", 0],
          ["TRUE", 1],
          ["true", 1],
          [1, true],
          [true, 1]
        ]);
      }
      this.labels.set(labelName, new Map(labels));
    });
    Object.keys(features.scalers || {}).forEach((scalerName) => {
      let transforms;
      const scalerData = features.scalers[scalerName];
      const { config } = scalerData;
      switch (config.strategy) {
        case "standard":
          transforms = util.StandardScalerTransforms(...[void 0, config.nan_value, config.return_nan, scalerData.components]);
          scalerData.scale = transforms.scale;
          scalerData.descale = transforms.descale;
          break;
        case "normalize":
        case "minmax":
          transforms = util.MinMaxScalerTransforms(...[void 0, config.nan_value, config.return_nan, scalerData.components]);
          scalerData.scale = transforms.scale;
          scalerData.descale = transforms.descale;
          break;
        case "log":
        default:
          scalerData.scale = Math.log;
          scalerData.descale = Math.exp;
          break;
      }
      this.scalers.set(scalerName, scalerData);
    });
  }
  filterColumn(filter = () => true) {
    return this.data.filter(filter);
  }
  columnScale(name, options = {}) {
    const input = typeof options === "string" ? { strategy: options } : options;
    const config = Object.assign({
      strategy: "log",
      forced_coercion: false
    }, input);
    let scaleData = config.data || this.columnArray(name, config.columnArrayOptions);
    let scaledData;
    let transforms;
    scaleData = scaleData.filter((datum) => typeof datum !== "undefined").map((datum, i) => {
      if (typeof datum !== "number") {
        if (this.config.debug && config.forced_coercion === false) {
          console.error(TypeError(`Each value must be a number, error at index [${name}][${i}]: <${typeof datum}>${datum}`));
        }
        const num = Number(datum);
        if (isNaN(num) && config.forced_coercion) {
          return 0;
        } else if (isNaN(num)) {
          throw TypeError(`Only numerical values in (${name}) can be scaled i: ${i} datum: ${datum}`);
        }
        return num;
      } else
        return datum;
    });
    switch (config.strategy) {
      case "standard":
        transforms = util.StandardScalerTransforms(...[scaleData, config.nan_value, config.return_nan]);
        this.scalers.set(name, {
          name,
          scale: transforms.scale,
          descale: transforms.descale,
          components: transforms.components
        });
        scaledData = transforms.values;
        break;
      case "normalize":
      case "minmax":
        transforms = util.MinMaxScalerTransforms(...[scaleData, config.nan_value, config.return_nan]);
        this.scalers.set(name, {
          name,
          scale: transforms.scale,
          descale: transforms.descale,
          components: transforms.components
        });
        scaledData = transforms.values;
        break;
      case "log":
      default:
        this.scalers.set(name, {
          name,
          scale: Math.log,
          descale: Math.exp,
          components: {
            average: util.avg(scaleData),
            standard_dev: util.sd(scaleData),
            maximum: util.max(scaleData),
            minimum: util.min(scaleData)
          }
        });
        scaledData = util.LogScaler(scaleData);
        break;
    }
    this.scalers.get(name).config = config;
    return scaledData;
  }
  columnDescale(name, options) {
    const config = Object.assign({}, options);
    const scaledData = config.data || this.columnArray(name, config.columnArrayOptions);
    const descaleFunction = this.scalers.get(name).descale;
    return scaledData.map(descaleFunction);
  }
  labelEncoder(name, options) {
    const config = Object.assign({
      binary: false,
      merge: true
    }, options);
    const labelData = config.data || this.columnArray(name, config.columnArrayOptions);
    let labelDataUniqueValues = Array.from(new Set(labelData).values()).sort(config.sortFunction);
    const labels = new Map(labelDataUniqueValues.reduce((result, val, i) => {
      if (config.binary) {
        if (i === 0) {
          result.push(...[
            [0, false],
            ["0", false],
            ["FALSE", 0],
            ["false", 0],
            [1, true],
            ["1", true],
            ["TRUE", 1],
            ["true", 1]
          ]);
        }
        result.push([val, _DataSet.getBinaryValue(val)]);
      } else {
        result.push([val, i]);
        result.push([i, val]);
      }
      return result;
    }, []));
    if (this.labels.has(name) && config.merge) {
      this.labels.set(name, new Map([...this.labels.get(name), ...labels]));
    } else
      this.labels.set(name, labels);
    const labeledData = config.binary ? labelData.map(_DataSet.getBinaryValue) : labelData.map((label) => labels.get(label));
    return labeledData;
  }
  labelDecode(name, options = {}) {
    const config = Object.assign({}, options);
    const labelData = config.data || this.columnArray(name, config.columnArrayOptions);
    return labelData.map((val) => this.labels.get(name).get(val));
  }
  oneHotColumnArray(name, options) {
    const config = Object.assign({}, options);
    const labels = config.labels || this.encoders.get(name).labels;
    const prefix = config.prefix || this.encoders.get(name).prefix;
    return this.selectColumns(labels.map((label) => `${prefix}${label}`));
  }
  columnReducer(name, options) {
    const newColumn = {
      [name]: this.columnArray(options.columnName, options.columnOptions).reduce(options.reducer, [])
    };
    return newColumn;
  }
  columnMerge(name, data = []) {
    if (this.data.length !== data.length)
      throw new RangeError(`Merged data column must have the same length(${data.length}) as the DataSet's length (${this.data.length})`);
    return {
      [name]: data
    };
  }
  inverseTransformObject(data, options) {
    const config = Object.assign({
      removeValues: false
    }, options);
    const removedColumns = [];
    let transformedObject = Object.assign({}, data);
    const columnNames = Object.keys(this.data[0]);
    const scaledData = columnNames.reduce((scaleObject, columnName) => {
      if (this.scalers.has(columnName)) {
        scaleObject[columnName] = this.scalers.get(columnName).descale(data[columnName]);
      }
      return scaleObject;
    }, {});
    const labeledData = columnNames.reduce((labelObject, columnName) => {
      if (this.labels.has(columnName)) {
        labelObject[columnName] = this.labels.get(columnName).get(data[columnName]);
      }
      return labelObject;
    }, {});
    const encodedData = columnNames.reduce((encodedObject, columnName) => {
      if (this.encoders.has(columnName)) {
        const encoded = this.oneHotDecoder(columnName, {
          data: [data]
        });
        encodedObject = Object.assign({}, encodedObject, encoded[0]);
        if (config.removeValues) {
          removedColumns.push(...this.encoders.get(columnName).labels.map((label) => `${this.encoders.get(columnName).prefix}${label}`));
        }
      }
      return encodedObject;
    }, {});
    transformedObject = Object.assign(transformedObject, scaledData, labeledData, encodedData);
    if (config.removeValues && removedColumns.length) {
      transformedObject = Object.keys(transformedObject).reduce((removedObject, propertyName) => {
        if (removedColumns.indexOf(propertyName) === -1) {
          removedObject[propertyName] = transformedObject[propertyName];
        }
        return removedObject;
      }, {});
    }
    return transformedObject;
  }
  transformObject(data, options) {
    const config = Object.assign({
      removeValues: false,
      checkColumnLength: true
    }, options);
    const removedColumns = [];
    const encodedColumns = new Array().concat(...Array.from(this.encoders.keys()).map((encodedColumn) => this.encoders.get(encodedColumn).labels.map((label) => `${this.encoders.get(encodedColumn).prefix}${label}`)));
    const currentColumns = this.data.length ? Object.keys(this.data[0]) : Object.keys(data);
    const objectColumns = Object.keys(data).concat(encodedColumns);
    const differentKeys = objectColumns.reduce((diffKeys, val) => {
      if (currentColumns.indexOf(val) === -1 && encodedColumns.indexOf(val) === -1)
        diffKeys.push(val);
      return diffKeys;
    }, []);
    let transformedObject = Object.assign({}, data);
    if (config.checkColumnLength && currentColumns.length !== objectColumns.length && currentColumns.length + encodedColumns.length !== objectColumns.length) {
      throw new RangeError(`Object must have the same number of keys (${objectColumns.length}) as data in your dataset(${currentColumns.length})`);
    } else if (config.checkColumnLength && differentKeys.length) {
      throw new ReferenceError(`Object must have identical keys as data in your DataSet. Invalid keys: ${differentKeys.join(",")}`);
    } else {
      const scaledData = objectColumns.reduce((scaleObject, columnName) => {
        if (this.scalers.has(columnName)) {
          scaleObject[columnName] = this.scalers.get(columnName).scale(data[columnName]);
        }
        return scaleObject;
      }, {});
      const labeledData = objectColumns.reduce((labelObject, columnName) => {
        if (this.labels.has(columnName)) {
          labelObject[columnName] = this.labels.get(columnName).get(data[columnName]);
        }
        return labelObject;
      }, {});
      const encodedData = objectColumns.reduce((encodedObject, columnName) => {
        if (this.encoders.has(columnName)) {
          encodedObject = Object.assign({}, encodedObject, this.encodeObject(data, this.encoders.get(columnName)));
          if (config.removeValues) {
            removedColumns.push(columnName);
          }
        }
        return encodedObject;
      }, {});
      transformedObject = Object.assign(transformedObject, scaledData, labeledData, encodedData);
      if (config.removeValues && removedColumns.length) {
        transformedObject = Object.keys(transformedObject).reduce((removedObject, propertyName) => {
          if (removedColumns.indexOf(propertyName) === -1)
            removedObject[propertyName] = transformedObject[propertyName];
          return removedObject;
        }, {});
      }
    }
    return transformedObject;
  }
  columnReplace(name, options = {}) {
    const config = Object.assign({
      strategy: "mean",
      empty: true,
      arrayOptions: {
        parseFloat: true,
        filter: (val) => val
      },
      labelOptions: {}
    }, options);
    let replaceVal;
    let replace = {
      test: (val) => !val,
      value: replaceVal
    };
    switch (config.strategy) {
      case "scale":
        replaceVal = this.columnScale(name, config.scaleOptions);
        replace = {
          test: (val) => true,
          value: (result, val, index, arr) => replaceVal[index]
        };
        break;
      case "descale":
        replaceVal = this.columnDescale(name, config.descaleOptions);
        replace = {
          test: (val) => true,
          value: (result, val, index, arr) => replaceVal[index]
        };
        break;
      case "label":
      case "labelEncoder":
        replaceVal = this.labelEncoder(name, config.labelOptions);
        replace = {
          test: (val) => true,
          value: (result, val, index, arr) => replaceVal[index]
        };
        break;
      case "labeldecode":
      case "labelDecode":
      case "labelDecoder":
        replaceVal = this.labelDecode(name, config.labelOptions);
        replace = {
          test: (val) => true,
          value: (result, val, index, arr) => replaceVal[index]
        };
        break;
      case "onehot":
      case "oneHot":
      case "oneHotEncode":
      case "oneHotEncoder":
        replaceVal = this.oneHotEncoder(name, config.oneHotOptions);
        replace = {
          test: (val) => true,
          value: (result, val, index, arr) => replaceVal[index]
        };
        return replaceVal;
      case "reducer":
      case "reduce":
        replaceVal = this.columnReducer(name, config.reducerOptions);
        return replaceVal;
      case "merge":
        replaceVal = this.columnMerge(name, config.mergeData);
        return replaceVal;
      case "parseNumber":
        replaceVal = this.columnArray(name).map((num) => Number(num));
        return replaceVal;
      default:
        replaceVal = import_ml_stat2.array[config.strategy](this.columnArray(name, config.arrayOptions));
        replace.value = replaceVal;
        break;
    }
    return this.columnArray(name, Object.assign({}, {
      replace,
      scale: options.scale
    }, options.columnOptions));
  }
  fitColumns(options = {}, mockDataOptions = {}) {
    const config = Object.assign({
      returnData: true,
      columns: []
    }, options);
    if (!options.columns || Array.isArray(options.columns) === false) {
      config.columns = options.columns ? _DataSet.getTransforms(options.columns) : _DataSet.getTransforms(options);
    }
    const fittedColumns = config.columns.reduce((result, val, index, arr) => {
      let replacedColumn = this.columnReplace(val.name, val.options);
      if (Array.isArray(replacedColumn)) {
        replacedColumn = replacedColumn.map((columnVal) => ({
          [val.name]: columnVal
        }));
        result[val.name] = replacedColumn;
      } else {
        Object.keys(replacedColumn).forEach((repColName) => {
          result[repColName] = replacedColumn[repColName].map((columnVal) => ({
            [repColName]: columnVal
          }));
        });
      }
      return result;
    }, {});
    if (Object.keys(fittedColumns) && Object.keys(fittedColumns).length) {
      const columnNames = Object.keys(fittedColumns);
      const fittedData = fittedColumns[columnNames[0]].reduce((result, val, index, arr) => {
        const returnObj = {};
        columnNames.forEach((colName) => {
          returnObj[colName] = fittedColumns[colName][index][colName];
        });
        result.push(returnObj);
        return result;
      }, []);
      this.data = this.data.map((val, index) => Object.assign({}, val, fittedData[index]));
    }
    return config.returnData ? this.data : this;
  }
  fitInverseTransforms(options = {}) {
    const config = Object.assign({
      returnData: true
    }, options);
    this.data = this.data.map((val) => {
      return options.removeValues ? this.inverseTransformObject(val, options) : Object.assign({}, val, this.inverseTransformObject(val, options));
    });
    return config.returnData ? this.data : this;
  }
  fitTransforms(options = {}) {
    const config = Object.assign({
      returnData: true
    }, options);
    this.data = this.data.map((val) => {
      return options.removeValues ? this.transformObject(val, options) : Object.assign({}, val, this.transformObject(val, options));
    });
    return config.returnData ? this.data : this;
  }
};
var DataSet = _DataSet;
__publicField(DataSet, "encoders");
__publicField(DataSet, "data");

// src/ColumnVectorizer.ts
var ColumnVectorizer = class {
  data;
  tokens;
  vectors;
  wordMap;
  wordCountMap;
  maxFeatures;
  sortedWordCount;
  limitedFeatures;
  matrix;
  replacer;
  constructor(options = {}) {
    try {
      if (typeof nlp.PorterStemmer === "undefined") {
        Object.assign(nlp, stub_default);
      }
    } catch (E) {
      console.error({ E });
    }
    this.data = options.data || [];
    this.tokens = /* @__PURE__ */ new Set();
    this.vectors = [];
    this.wordMap = {};
    this.wordCountMap = {};
    this.maxFeatures = options.maxFeatures;
    this.sortedWordCount = [];
    this.limitedFeatures = [];
    this.matrix = [];
    this.replacer = (value = "") => {
      const cleanedValue = value.toLowerCase().replace(/[^a-zA-Z]/gi, " ");
      return nlp.PorterStemmer.tokenizeAndStem(cleanedValue).join(" ");
    };
    return this;
  }
  get_tokens() {
    return Array.from(this.tokens);
  }
  get_vector_array() {
    return this.get_tokens().map((tok) => [
      tok
    ]);
  }
  fit_transform(options = {}) {
    const data = options.data || this.data;
    data.forEach((datum) => {
      const datums = {};
      this.replacer(datum).split(" ").forEach((tok) => {
        const token = tok.toLowerCase();
        datums[token] = datums[token] ? datums[token] + 1 : 1;
        this.wordCountMap[token] = this.wordCountMap[token] ? this.wordCountMap[token] + 1 : 1;
        this.tokens.add(token);
      });
      this.vectors.push(datums);
    });
    this.wordMap = Array.from(this.tokens).reduce((result, value) => {
      result[value] = 0;
      return result;
    }, {});
    this.sortedWordCount = Object.keys(this.wordCountMap).sort((a, b) => this.wordCountMap[b] - this.wordCountMap[a]);
    this.vectors = this.vectors.map((vector) => Object.assign({}, this.wordMap, vector));
    const vectorData = new DataSet(this.vectors);
    this.limitedFeatures = this.get_limited_features(options);
    this.matrix = vectorData.columnMatrix(this.limitedFeatures);
    return this.matrix;
  }
  get_limited_features(options = {}) {
    const maxFeatures = options.maxFeatures || this.maxFeatures || this.tokens.size;
    return this.sortedWordCount.slice(0, maxFeatures).map((feature) => [feature]);
  }
  evaluateString(testString = "") {
    const evalString = this.replacer(testString);
    const evalStringWordMap = evalString.split(" ").reduce((result, value) => {
      if (this.tokens.has(value)) {
        result[value] = result[value] !== void 0 ? result[value] + 1 : 1;
      }
      return result;
    }, {});
    return {
      ...this.wordMap,
      ...evalStringWordMap
    };
  }
  evaluate(testString = "", options) {
    const stringObj = this.evaluateString(testString);
    const limitedFeatures = this.get_limited_features(options);
    const vectorData = new DataSet([
      stringObj
    ]);
    return vectorData.columnMatrix(limitedFeatures);
  }
};

// src/nlp.ts
var nlp = Object.assign({
  ColumnVectorizer
});

// src/cross_validation.ts
var import_random_js = require("random-js");
var import_lodash3 = __toESM(require("lodash.range"), 1);
var import_ml_matrix = require("ml-matrix");
var import_ml_confusion_matrix = __toESM(require("ml-confusion-matrix"), 1);
var import_js_grid_search_lite = __toESM(require("js-grid-search-lite"), 1);
var { GridSearch } = import_js_grid_search_lite.default;
function train_test_split(dataset = [], options = {
  test_size: 0.2,
  train_size: 0.8,
  random_state: 0,
  return_array: false,
  parse_int_train_size: true
}) {
  const engine = import_random_js.MersenneTwister19937.seed(options.random_state || 0);
  const training_set = [];
  const parse_int_train_size = typeof options.parse_int_train_size === "boolean" ? options.parse_int_train_size : true;
  const train_size_length = options.train_size ? options.train_size * dataset.length : (1 - (options.test_size || 0.2)) * dataset.length;
  const train_size = parse_int_train_size ? parseInt(train_size_length.toString(), 10) : train_size_length;
  const dataset_copy = new Array().concat(dataset);
  while (training_set.length < train_size) {
    const index = (0, import_random_js.integer)(0, dataset_copy.length - 1)(engine);
    training_set.push(dataset_copy.splice(index, 1)[0]);
  }
  return options.return_array ? [training_set, dataset_copy] : {
    train: training_set,
    test: dataset_copy
  };
}
function cross_validation_split(dataset = [], options = {
  folds: 3,
  random_state: 0
}) {
  const engine = import_random_js.MersenneTwister19937.seed(options.random_state || 0);
  const folds = options.folds || 3;
  const dataset_split = [];
  const dataset_copy = [].concat(dataset);
  const foldLength = dataset.length / (folds || 3);
  const foldsize = Math.floor(foldLength);
  for (let i in (0, import_lodash3.default)(folds)) {
    const fold = [];
    while (fold.length < foldsize) {
      const index = (0, import_random_js.integer)(0, dataset_copy.length - 1)(engine);
      fold.push(dataset_copy.splice(index, 1)[0]);
    }
    dataset_split.push(fold);
  }
  return dataset_split;
}
function cross_validate_score(options = {}) {
  const config = {
    dependentFeatures: [["X"]],
    independentFeatures: [["Y"]],
    folds: 10,
    accuracy: "standardError",
    use_train_x_matrix: true,
    use_train_y_matrix: false,
    use_train_y_vector: false,
    use_estimates_y_vector: false,
    ...options
  };
  const classifier = config.classifier;
  const regression = config.regression;
  const folds = cross_validation_split(config.dataset, {
    folds: config.folds,
    random_state: config.random_state
  });
  const testingDataSet = new DataSet(config.testingset);
  const y_test_matrix = testingDataSet.columnMatrix(config.independentFeatures);
  const x_test_matrix = testingDataSet.columnMatrix(config.dependentFeatures);
  const actuals = util.pivotVector(y_test_matrix)[0];
  const prediction_accuracies = folds.map((fold) => {
    const trainingDataSet = new DataSet(fold);
    const x_train = trainingDataSet.columnMatrix(config.dependentFeatures);
    const y_train = trainingDataSet.columnMatrix(config.independentFeatures);
    const x_train_matrix = config.use_train_x_matrix ? new import_ml_matrix.Matrix(x_train) : x_train;
    const y_train_matrix = config.use_train_y_matrix ? new import_ml_matrix.Matrix(y_train) : config.use_train_y_vector ? util.pivotVector(y_train)[0] : y_train;
    if (regression) {
      let regressor;
      let pred_y_test;
      if (typeof regression.train === "function") {
        regressor = regression.train(x_train_matrix, y_train_matrix, config.modelOptions);
        pred_y_test = regression.predict(x_test_matrix);
      } else {
        regressor = new regression(x_train_matrix, y_train_matrix, config.modelOptions);
        pred_y_test = regressor.predict(x_test_matrix);
      }
      const estimates = pred_y_test;
      return config.accuracy === "standardError" ? util.standardError(actuals, estimates) : util.rSquared(actuals, estimates);
    } else {
      let classification;
      let estimates;
      if (typeof classifier.train === "function") {
        classifier.train(x_train_matrix, y_train_matrix, config.modelOptions);
        estimates = classifier.predict(x_test_matrix);
      } else {
        classification = new classifier(x_train_matrix, y_train_matrix, config.modelOptions);
        estimates = classification.predict(x_test_matrix);
      }
      const compareEstimates = config.use_estimates_y_vector ? util.pivotVector(estimates)[0] : estimates;
      const CM = import_ml_confusion_matrix.default.fromLabels(actuals, compareEstimates);
      return CM.getAccuracy();
    }
  });
  return prediction_accuracies;
}
function grid_search(options = {}) {
  const config = {
    return_parameters: false,
    compare_score: "mean",
    sortAccuracyScore: "desc",
    parameters: {},
    ...options
  };
  const regressor = config.regression;
  const classification = config.classifier;
  const sortAccuracyScore = !options.sortAccuracyScore && config.regression ? "asc" : config.sortAccuracyScore;
  const gs = new GridSearch({
    params: config.parameters,
    run_callback: (params) => {
      if (config.regression) {
        config.regression = new regressor(params);
      } else {
        config.classifier = new classification(params);
      }
      const score = cross_validate_score(config);
      return config.compare_score ? util[config.compare_score](score) : score;
    }
  });
  gs.run();
  const accuracySorter = sortAccuracyScore === "desc" ? (a, b) => b.results - a.results : (a, b) => a.results - b.results;
  const results = gs._results.sort(accuracySorter);
  return config.return_parameters ? results : results[0];
}
var cross_validation = {
  train_test_split,
  cross_validation_split,
  kfolds: cross_validation_split,
  cross_validate_score,
  grid_search,
  GridSearch
};

// src/calc.ts
var fpg = __toESM(require("node-fpgrowth"), 1);
var { FPGrowth } = fpg;
function getTransactions(data, options) {
  const config = Object.assign({}, {
    exludeEmptyTranscations: true
  }, options);
  const values = /* @__PURE__ */ new Set();
  const valuesMap = /* @__PURE__ */ new Map();
  const transactions = data.map((csvRow) => {
    [
      ...Object.values(csvRow)
    ].forEach((csvVal) => {
      values.add(csvVal);
    });
    values.forEach((val) => {
      if (!valuesMap.get(val)) {
        const index = valuesMap.size < 0 ? 0 : Math.round(valuesMap.size / 2);
        valuesMap.set(val, index.toString());
        valuesMap.set(index.toString(), val);
      }
    });
    return Object.values(csvRow).map((csvCell) => valuesMap.get(csvCell)).filter((val) => val !== void 0);
  });
  return {
    values,
    valuesMap,
    transactions: config.exludeEmptyTranscations ? transactions.filter((csvRow) => csvRow.length) : transactions
  };
}
function assocationRuleLearning(transactions = [], options) {
  return new Promise((resolve, reject) => {
    try {
      const config = Object.assign({}, {
        support: 0.4,
        minLength: 2,
        summary: true,
        valuesMap: /* @__PURE__ */ new Map()
      }, options);
      const fpgrowth = new FPGrowth(config.support);
      fpgrowth.exec(transactions).then((results) => {
        const itemsets = results.itemsets ? results.itemsets : results;
        if (config.summary) {
          resolve(itemsets.map((itemset) => ({
            items_labels: itemset.items.map((item) => config.valuesMap.get(item)),
            items: itemset.items,
            support: itemset.support,
            support_percent: itemset.support / transactions.length
          })).filter((itemset) => itemset.items.length > 1).sort((a, b) => b.support - a.support));
        } else {
          resolve(results);
        }
      }).catch(reject);
    } catch (e) {
      reject(e);
    }
  });
}
var calc = {
  getTransactions,
  assocationRuleLearning
};

// src/index.ts
var csv2 = csv_exports;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  DataSet,
  PD,
  calc,
  cross_validation,
  csv,
  nlp,
  util
});
