rowpipe 2.2.1 → 2.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -4
- package/dist/analytics/abtest.d.ts +39 -0
- package/dist/analytics/abtest.d.ts.map +1 -0
- package/dist/analytics/abtest.js +266 -0
- package/dist/analytics/abtest.js.map +1 -0
- package/dist/analytics/cluster.d.ts +25 -0
- package/dist/analytics/cluster.d.ts.map +1 -0
- package/dist/analytics/cluster.js +212 -0
- package/dist/analytics/cluster.js.map +1 -0
- package/dist/analytics/cohort.d.ts +22 -0
- package/dist/analytics/cohort.d.ts.map +1 -0
- package/dist/analytics/cohort.js +170 -0
- package/dist/analytics/cohort.js.map +1 -0
- package/dist/analytics/correlation.d.ts +15 -0
- package/dist/analytics/correlation.d.ts.map +1 -0
- package/dist/analytics/correlation.js +116 -0
- package/dist/analytics/correlation.js.map +1 -0
- package/dist/analytics/crosstab.d.ts +27 -0
- package/dist/analytics/crosstab.d.ts.map +1 -0
- package/dist/analytics/crosstab.js +90 -0
- package/dist/analytics/crosstab.js.map +1 -0
- package/dist/analytics/entropy.d.ts +23 -0
- package/dist/analytics/entropy.d.ts.map +1 -0
- package/dist/analytics/entropy.js +180 -0
- package/dist/analytics/entropy.js.map +1 -0
- package/dist/analytics/funnel.d.ts +29 -0
- package/dist/analytics/funnel.d.ts.map +1 -0
- package/dist/analytics/funnel.js +170 -0
- package/dist/analytics/funnel.js.map +1 -0
- package/dist/analytics/ngrams.d.ts +25 -0
- package/dist/analytics/ngrams.d.ts.map +1 -0
- package/dist/analytics/ngrams.js +110 -0
- package/dist/analytics/ngrams.js.map +1 -0
- package/dist/analytics/outliers.d.ts +25 -0
- package/dist/analytics/outliers.d.ts.map +1 -0
- package/dist/analytics/outliers.js +114 -0
- package/dist/analytics/outliers.js.map +1 -0
- package/dist/analytics/pareto.d.ts +36 -0
- package/dist/analytics/pareto.d.ts.map +1 -0
- package/dist/analytics/pareto.js +140 -0
- package/dist/analytics/pareto.js.map +1 -0
- package/dist/analytics/quantiles.d.ts +18 -0
- package/dist/analytics/quantiles.d.ts.map +1 -0
- package/dist/analytics/quantiles.js +62 -0
- package/dist/analytics/quantiles.js.map +1 -0
- package/dist/analytics/regression.d.ts +18 -0
- package/dist/analytics/regression.d.ts.map +1 -0
- package/dist/analytics/regression.js +79 -0
- package/dist/analytics/regression.js.map +1 -0
- package/dist/analytics/rfm.d.ts +41 -0
- package/dist/analytics/rfm.d.ts.map +1 -0
- package/dist/analytics/rfm.js +221 -0
- package/dist/analytics/rfm.js.map +1 -0
- package/dist/analytics/stats.d.ts.map +1 -1
- package/dist/analytics/stats.js +65 -15
- package/dist/analytics/stats.js.map +1 -1
- package/dist/analytics/technical.d.ts +19 -0
- package/dist/analytics/technical.d.ts.map +1 -0
- package/dist/analytics/technical.js +365 -0
- package/dist/analytics/technical.js.map +1 -0
- package/dist/cli/commands/abtest.d.ts +10 -0
- package/dist/cli/commands/abtest.d.ts.map +1 -0
- package/dist/cli/commands/abtest.js +68 -0
- package/dist/cli/commands/abtest.js.map +1 -0
- package/dist/cli/commands/cluster.d.ts +9 -0
- package/dist/cli/commands/cluster.d.ts.map +1 -0
- package/dist/cli/commands/cluster.js +77 -0
- package/dist/cli/commands/cluster.js.map +1 -0
- package/dist/cli/commands/cohort.d.ts +10 -0
- package/dist/cli/commands/cohort.d.ts.map +1 -0
- package/dist/cli/commands/cohort.js +66 -0
- package/dist/cli/commands/cohort.js.map +1 -0
- package/dist/cli/commands/completion.d.ts +5 -0
- package/dist/cli/commands/completion.d.ts.map +1 -0
- package/dist/cli/commands/completion.js +7 -0
- package/dist/cli/commands/completion.js.map +1 -0
- package/dist/cli/commands/concat.d.ts +9 -0
- package/dist/cli/commands/concat.d.ts.map +1 -0
- package/dist/cli/commands/concat.js +62 -0
- package/dist/cli/commands/concat.js.map +1 -0
- package/dist/cli/commands/convert.d.ts +2 -0
- package/dist/cli/commands/convert.d.ts.map +1 -1
- package/dist/cli/commands/convert.js.map +1 -1
- package/dist/cli/commands/corr.d.ts +7 -0
- package/dist/cli/commands/corr.d.ts.map +1 -0
- package/dist/cli/commands/corr.js +70 -0
- package/dist/cli/commands/corr.js.map +1 -0
- package/dist/cli/commands/crosstab.d.ts +11 -0
- package/dist/cli/commands/crosstab.d.ts.map +1 -0
- package/dist/cli/commands/crosstab.js +71 -0
- package/dist/cli/commands/crosstab.js.map +1 -0
- package/dist/cli/commands/entropy.d.ts +9 -0
- package/dist/cli/commands/entropy.d.ts.map +1 -0
- package/dist/cli/commands/entropy.js +71 -0
- package/dist/cli/commands/entropy.js.map +1 -0
- package/dist/cli/commands/explode.d.ts +8 -0
- package/dist/cli/commands/explode.d.ts.map +1 -0
- package/dist/cli/commands/explode.js +61 -0
- package/dist/cli/commands/explode.js.map +1 -0
- package/dist/cli/commands/fetch.d.ts +8 -0
- package/dist/cli/commands/fetch.d.ts.map +1 -0
- package/dist/cli/commands/fetch.js +41 -0
- package/dist/cli/commands/fetch.js.map +1 -0
- package/dist/cli/commands/files.d.ts +1 -1
- package/dist/cli/commands/files.d.ts.map +1 -1
- package/dist/cli/commands/flatten.d.ts +8 -0
- package/dist/cli/commands/flatten.d.ts.map +1 -0
- package/dist/cli/commands/flatten.js +57 -0
- package/dist/cli/commands/flatten.js.map +1 -0
- package/dist/cli/commands/freq.d.ts +10 -0
- package/dist/cli/commands/freq.d.ts.map +1 -0
- package/dist/cli/commands/freq.js +122 -0
- package/dist/cli/commands/freq.js.map +1 -0
- package/dist/cli/commands/funnel.d.ts +11 -0
- package/dist/cli/commands/funnel.d.ts.map +1 -0
- package/dist/cli/commands/funnel.js +69 -0
- package/dist/cli/commands/funnel.js.map +1 -0
- package/dist/cli/commands/fuzzy-join.d.ts +25 -0
- package/dist/cli/commands/fuzzy-join.d.ts.map +1 -0
- package/dist/cli/commands/fuzzy-join.js +85 -0
- package/dist/cli/commands/fuzzy-join.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +8 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +34 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/mask.d.ts +6 -0
- package/dist/cli/commands/mask.d.ts.map +1 -0
- package/dist/cli/commands/mask.js +58 -0
- package/dist/cli/commands/mask.js.map +1 -0
- package/dist/cli/commands/ngrams.d.ts +11 -0
- package/dist/cli/commands/ngrams.d.ts.map +1 -0
- package/dist/cli/commands/ngrams.js +70 -0
- package/dist/cli/commands/ngrams.js.map +1 -0
- package/dist/cli/commands/outliers.d.ts +13 -0
- package/dist/cli/commands/outliers.d.ts.map +1 -0
- package/dist/cli/commands/outliers.js +58 -0
- package/dist/cli/commands/outliers.js.map +1 -0
- package/dist/cli/commands/pareto.d.ts +8 -0
- package/dist/cli/commands/pareto.d.ts.map +1 -0
- package/dist/cli/commands/pareto.js +80 -0
- package/dist/cli/commands/pareto.js.map +1 -0
- package/dist/cli/commands/partition.d.ts +8 -0
- package/dist/cli/commands/partition.d.ts.map +1 -0
- package/dist/cli/commands/partition.js +44 -0
- package/dist/cli/commands/partition.js.map +1 -0
- package/dist/cli/commands/pipeline.d.ts +6 -0
- package/dist/cli/commands/pipeline.d.ts.map +1 -1
- package/dist/cli/commands/pipeline.js +22 -0
- package/dist/cli/commands/pipeline.js.map +1 -1
- package/dist/cli/commands/pivot.d.ts +11 -0
- package/dist/cli/commands/pivot.d.ts.map +1 -0
- package/dist/cli/commands/pivot.js +58 -0
- package/dist/cli/commands/pivot.js.map +1 -0
- package/dist/cli/commands/plot.d.ts +12 -0
- package/dist/cli/commands/plot.d.ts.map +1 -0
- package/dist/cli/commands/plot.js +123 -0
- package/dist/cli/commands/plot.js.map +1 -0
- package/dist/cli/commands/quantiles.d.ts +7 -0
- package/dist/cli/commands/quantiles.d.ts.map +1 -0
- package/dist/cli/commands/quantiles.js +94 -0
- package/dist/cli/commands/quantiles.js.map +1 -0
- package/dist/cli/commands/regression.d.ts +7 -0
- package/dist/cli/commands/regression.d.ts.map +1 -0
- package/dist/cli/commands/regression.js +86 -0
- package/dist/cli/commands/regression.js.map +1 -0
- package/dist/cli/commands/report.d.ts +8 -0
- package/dist/cli/commands/report.d.ts.map +1 -0
- package/dist/cli/commands/report.js +36 -0
- package/dist/cli/commands/report.js.map +1 -0
- package/dist/cli/commands/rfm.d.ts +11 -0
- package/dist/cli/commands/rfm.d.ts.map +1 -0
- package/dist/cli/commands/rfm.js +78 -0
- package/dist/cli/commands/rfm.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +7 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +43 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/split.d.ts +8 -0
- package/dist/cli/commands/split.d.ts.map +1 -0
- package/dist/cli/commands/split.js +43 -0
- package/dist/cli/commands/split.js.map +1 -0
- package/dist/cli/commands/table.d.ts +9 -0
- package/dist/cli/commands/table.d.ts.map +1 -0
- package/dist/cli/commands/table.js +9 -0
- package/dist/cli/commands/table.js.map +1 -0
- package/dist/cli/commands/technical.d.ts +8 -0
- package/dist/cli/commands/technical.d.ts.map +1 -0
- package/dist/cli/commands/technical.js +54 -0
- package/dist/cli/commands/technical.js.map +1 -0
- package/dist/cli/commands/test.d.ts +7 -0
- package/dist/cli/commands/test.d.ts.map +1 -0
- package/dist/cli/commands/test.js +53 -0
- package/dist/cli/commands/test.js.map +1 -0
- package/dist/cli/commands/timeseries.d.ts +11 -0
- package/dist/cli/commands/timeseries.d.ts.map +1 -0
- package/dist/cli/commands/timeseries.js +82 -0
- package/dist/cli/commands/timeseries.js.map +1 -0
- package/dist/cli/commands/unpivot.d.ts +12 -0
- package/dist/cli/commands/unpivot.d.ts.map +1 -0
- package/dist/cli/commands/unpivot.js +59 -0
- package/dist/cli/commands/unpivot.js.map +1 -0
- package/dist/cli/completion.d.ts +5 -0
- package/dist/cli/completion.d.ts.map +1 -0
- package/dist/cli/completion.js +194 -0
- package/dist/cli/completion.js.map +1 -0
- package/dist/cli/index.js +816 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/core/error-handler.d.ts +38 -0
- package/dist/core/error-handler.d.ts.map +1 -0
- package/dist/core/error-handler.js +81 -0
- package/dist/core/error-handler.js.map +1 -0
- package/dist/core/pipeline.d.ts +10 -0
- package/dist/core/pipeline.d.ts.map +1 -1
- package/dist/core/pipeline.js +14 -0
- package/dist/core/pipeline.js.map +1 -1
- package/dist/core/types.d.ts +4 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/dataops/fetch.d.ts +27 -0
- package/dist/dataops/fetch.d.ts.map +1 -0
- package/dist/dataops/fetch.js +150 -0
- package/dist/dataops/fetch.js.map +1 -0
- package/dist/dataops/generate.d.ts +16 -0
- package/dist/dataops/generate.d.ts.map +1 -0
- package/dist/dataops/generate.js +201 -0
- package/dist/dataops/generate.js.map +1 -0
- package/dist/dataops/mask.d.ts +25 -0
- package/dist/dataops/mask.d.ts.map +1 -0
- package/dist/dataops/mask.js +133 -0
- package/dist/dataops/mask.js.map +1 -0
- package/dist/dataops/report.d.ts +7 -0
- package/dist/dataops/report.d.ts.map +1 -0
- package/dist/dataops/report.js +139 -0
- package/dist/dataops/report.js.map +1 -0
- package/dist/dataops/server.d.ts +10 -0
- package/dist/dataops/server.d.ts.map +1 -0
- package/dist/dataops/server.js +137 -0
- package/dist/dataops/server.js.map +1 -0
- package/dist/dataops/test-runner.d.ts +34 -0
- package/dist/dataops/test-runner.d.ts.map +1 -0
- package/dist/dataops/test-runner.js +128 -0
- package/dist/dataops/test-runner.js.map +1 -0
- package/dist/db/adapters/sqlite.d.ts.map +1 -1
- package/dist/db/adapters/sqlite.js +4 -1
- package/dist/db/adapters/sqlite.js.map +1 -1
- package/dist/diff/engine.d.ts.map +1 -1
- package/dist/diff/engine.js +73 -16
- package/dist/diff/engine.js.map +1 -1
- package/dist/diff/storage/disk-index.d.ts +10 -1
- package/dist/diff/storage/disk-index.d.ts.map +1 -1
- package/dist/diff/storage/disk-index.js +95 -13
- package/dist/diff/storage/disk-index.js.map +1 -1
- package/dist/files/hash.d.ts +9 -2
- package/dist/files/hash.d.ts.map +1 -1
- package/dist/files/hash.js +9 -10
- package/dist/files/hash.js.map +1 -1
- package/dist/files/reader.d.ts.map +1 -1
- package/dist/files/reader.js +17 -10
- package/dist/files/reader.js.map +1 -1
- package/dist/files/types.d.ts +2 -1
- package/dist/files/types.d.ts.map +1 -1
- package/dist/index.d.ts +65 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +66 -1
- package/dist/index.js.map +1 -1
- package/dist/planner/executor.d.ts.map +1 -1
- package/dist/planner/executor.js +17 -0
- package/dist/planner/executor.js.map +1 -1
- package/dist/planner/types.d.ts +11 -0
- package/dist/planner/types.d.ts.map +1 -1
- package/dist/readers/csv.d.ts.map +1 -1
- package/dist/readers/csv.js +206 -164
- package/dist/readers/csv.js.map +1 -1
- package/dist/readers/json.d.ts.map +1 -1
- package/dist/readers/json.js +145 -121
- package/dist/readers/json.js.map +1 -1
- package/dist/readers/jsonl.d.ts.map +1 -1
- package/dist/readers/jsonl.js +51 -31
- package/dist/readers/jsonl.js.map +1 -1
- package/dist/transforms/concat.d.ts +26 -0
- package/dist/transforms/concat.d.ts.map +1 -0
- package/dist/transforms/concat.js +57 -0
- package/dist/transforms/concat.js.map +1 -0
- package/dist/transforms/explode.d.ts +14 -0
- package/dist/transforms/explode.d.ts.map +1 -0
- package/dist/transforms/explode.js +81 -0
- package/dist/transforms/explode.js.map +1 -0
- package/dist/transforms/flatten.d.ts +12 -0
- package/dist/transforms/flatten.d.ts.map +1 -0
- package/dist/transforms/flatten.js +65 -0
- package/dist/transforms/flatten.js.map +1 -0
- package/dist/transforms/fuzzy-join.d.ts +53 -0
- package/dist/transforms/fuzzy-join.d.ts.map +1 -0
- package/dist/transforms/fuzzy-join.js +347 -0
- package/dist/transforms/fuzzy-join.js.map +1 -0
- package/dist/transforms/jit-compiler.d.ts.map +1 -1
- package/dist/transforms/jit-compiler.js +103 -14
- package/dist/transforms/jit-compiler.js.map +1 -1
- package/dist/transforms/map.d.ts +6 -2
- package/dist/transforms/map.d.ts.map +1 -1
- package/dist/transforms/map.js +64 -26
- package/dist/transforms/map.js.map +1 -1
- package/dist/transforms/partition.d.ts +35 -0
- package/dist/transforms/partition.d.ts.map +1 -0
- package/dist/transforms/partition.js +150 -0
- package/dist/transforms/partition.js.map +1 -0
- package/dist/transforms/pivot.d.ts +16 -0
- package/dist/transforms/pivot.d.ts.map +1 -0
- package/dist/transforms/pivot.js +194 -0
- package/dist/transforms/pivot.js.map +1 -0
- package/dist/transforms/sort/comparator.d.ts.map +1 -1
- package/dist/transforms/sort/comparator.js +153 -24
- package/dist/transforms/sort/comparator.js.map +1 -1
- package/dist/transforms/sort/external-sort.js +1 -1
- package/dist/transforms/sort/external-sort.js.map +1 -1
- package/dist/transforms/split.d.ts +17 -0
- package/dist/transforms/split.d.ts.map +1 -0
- package/dist/transforms/split.js +88 -0
- package/dist/transforms/split.js.map +1 -0
- package/dist/transforms/timeseries.d.ts +42 -0
- package/dist/transforms/timeseries.d.ts.map +1 -0
- package/dist/transforms/timeseries.js +276 -0
- package/dist/transforms/timeseries.js.map +1 -0
- package/dist/transforms/unpivot.d.ts +14 -0
- package/dist/transforms/unpivot.d.ts.map +1 -0
- package/dist/transforms/unpivot.js +56 -0
- package/dist/transforms/unpivot.js.map +1 -0
- package/dist/ui/chart.d.ts +30 -0
- package/dist/ui/chart.d.ts.map +1 -0
- package/dist/ui/chart.js +91 -0
- package/dist/ui/chart.js.map +1 -0
- package/dist/writers/index.d.ts +1 -0
- package/dist/writers/index.d.ts.map +1 -1
- package/dist/writers/index.js +10 -0
- package/dist/writers/index.js.map +1 -1
- package/dist/writers/table.d.ts +23 -0
- package/dist/writers/table.d.ts.map +1 -0
- package/dist/writers/table.js +156 -0
- package/dist/writers/table.js.map +1 -0
- package/package.json +6 -3
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streaming Outlier & Anomaly Detection Transform.
|
|
3
|
+
*/
|
|
4
|
+
export function outliersTransform(options) {
|
|
5
|
+
const col = options.column;
|
|
6
|
+
const method = options.method || "zscore";
|
|
7
|
+
const threshold = options.threshold !== undefined
|
|
8
|
+
? options.threshold
|
|
9
|
+
: method === "iqr"
|
|
10
|
+
? 1.5
|
|
11
|
+
: 3.0;
|
|
12
|
+
return async function* (input) {
|
|
13
|
+
// Pass 1: Collect numeric stats
|
|
14
|
+
const allRows = [];
|
|
15
|
+
const values = [];
|
|
16
|
+
let sum = 0;
|
|
17
|
+
for await (const batch of input) {
|
|
18
|
+
for (const row of batch.rows) {
|
|
19
|
+
allRows.push(row);
|
|
20
|
+
const rawVal = row[col];
|
|
21
|
+
if (rawVal !== null && rawVal !== undefined && rawVal !== "") {
|
|
22
|
+
const num = typeof rawVal === "number" ? rawVal : parseFloat(String(rawVal));
|
|
23
|
+
if (Number.isFinite(num)) {
|
|
24
|
+
values.push(num);
|
|
25
|
+
sum += num;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (values.length === 0) {
|
|
31
|
+
yield { rows: allRows, offset: 0 };
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// Compute statistical boundaries
|
|
35
|
+
let isOutlierFn;
|
|
36
|
+
if (method === "zscore") {
|
|
37
|
+
const n = values.length;
|
|
38
|
+
const mean = sum / n;
|
|
39
|
+
const variance = values.reduce((acc, v) => acc + (v - mean) ** 2, 0) / (n > 1 ? n - 1 : 1);
|
|
40
|
+
const stddev = Math.sqrt(variance);
|
|
41
|
+
isOutlierFn = (v) => {
|
|
42
|
+
if (stddev === 0)
|
|
43
|
+
return { isOutlier: false, score: 0 };
|
|
44
|
+
const z = (v - mean) / stddev;
|
|
45
|
+
const score = parseFloat(z.toFixed(3));
|
|
46
|
+
return { isOutlier: Math.abs(z) > threshold, score };
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
else if (method === "iqr") {
|
|
50
|
+
values.sort((a, b) => a - b);
|
|
51
|
+
const n = values.length;
|
|
52
|
+
const q1 = values[Math.floor(0.25 * (n - 1))];
|
|
53
|
+
const q3 = values[Math.floor(0.75 * (n - 1))];
|
|
54
|
+
const iqr = q3 - q1;
|
|
55
|
+
const lower = q1 - threshold * iqr;
|
|
56
|
+
const upper = q3 + threshold * iqr;
|
|
57
|
+
isOutlierFn = (v) => {
|
|
58
|
+
const isOut = v < lower || v > upper;
|
|
59
|
+
const dist = v < lower ? lower - v : v > upper ? v - upper : 0;
|
|
60
|
+
const score = iqr > 0 ? parseFloat((dist / iqr).toFixed(3)) : 0;
|
|
61
|
+
return { isOutlier: isOut, score };
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// MAD (Median Absolute Deviation)
|
|
66
|
+
values.sort((a, b) => a - b);
|
|
67
|
+
const median = values[Math.floor(values.length / 2)];
|
|
68
|
+
const absDevs = values.map((v) => Math.abs(v - median)).sort((a, b) => a - b);
|
|
69
|
+
const mad = absDevs[Math.floor(absDevs.length / 2)] || 0.0001;
|
|
70
|
+
isOutlierFn = (v) => {
|
|
71
|
+
const modZ = (0.6745 * Math.abs(v - median)) / mad;
|
|
72
|
+
const score = parseFloat(modZ.toFixed(3));
|
|
73
|
+
return { isOutlier: modZ > threshold, score };
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
// Pass 2: Filter or annotate rows
|
|
77
|
+
const outRows = [];
|
|
78
|
+
for (const row of allRows) {
|
|
79
|
+
const rawVal = row[col];
|
|
80
|
+
const num = typeof rawVal === "number" ? rawVal : parseFloat(String(rawVal));
|
|
81
|
+
const hasValidNum = Number.isFinite(num);
|
|
82
|
+
const check = hasValidNum ? isOutlierFn(num) : { isOutlier: false, score: 0 };
|
|
83
|
+
if (options.onlyOutliers) {
|
|
84
|
+
if (check.isOutlier) {
|
|
85
|
+
if (options.addColumns) {
|
|
86
|
+
outRows.push({ ...row, _is_outlier: true, _outlier_score: check.score });
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
outRows.push(row);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else if (options.invert) {
|
|
94
|
+
if (!check.isOutlier) {
|
|
95
|
+
outRows.push(row);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
if (options.addColumns) {
|
|
100
|
+
outRows.push({
|
|
101
|
+
...row,
|
|
102
|
+
_is_outlier: check.isOutlier,
|
|
103
|
+
_outlier_score: check.score,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
outRows.push(row);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
yield { rows: outRows, offset: 0 };
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=outliers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outliers.js","sourceRoot":"","sources":["../../src/analytics/outliers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Row, DataBatch } from "../core/types.js";
|
|
2
|
+
export interface ParetoOptions {
|
|
3
|
+
itemCol?: string;
|
|
4
|
+
valueCol?: string;
|
|
5
|
+
aThreshold?: number;
|
|
6
|
+
bThreshold?: number;
|
|
7
|
+
summary?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ParetoItemResult {
|
|
10
|
+
rank: number;
|
|
11
|
+
item: string;
|
|
12
|
+
value: number;
|
|
13
|
+
share_pct: number;
|
|
14
|
+
cumulative_value: number;
|
|
15
|
+
cumulative_pct: number;
|
|
16
|
+
abc_class: "A" | "B" | "C";
|
|
17
|
+
}
|
|
18
|
+
export interface ParetoSummaryCategory {
|
|
19
|
+
abc_class: "A" | "B" | "C";
|
|
20
|
+
item_count: number;
|
|
21
|
+
item_percentage: number;
|
|
22
|
+
total_value: number;
|
|
23
|
+
value_percentage: number;
|
|
24
|
+
description: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ParetoResult {
|
|
27
|
+
items: ParetoItemResult[];
|
|
28
|
+
summary: ParetoSummaryCategory[];
|
|
29
|
+
total_items: number;
|
|
30
|
+
total_value: number;
|
|
31
|
+
pareto_80_item_count: number;
|
|
32
|
+
pareto_80_item_percentage: number;
|
|
33
|
+
formattedRows: Row[];
|
|
34
|
+
}
|
|
35
|
+
export declare function computePareto(batchIterator: AsyncIterable<DataBatch>, options?: ParetoOptions): Promise<ParetoResult>;
|
|
36
|
+
//# sourceMappingURL=pareto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pareto.d.ts","sourceRoot":"","sources":["../../src/analytics/pareto.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;CAC5B;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,yBAAyB,EAAE,MAAM,CAAC;IAClC,aAAa,EAAE,GAAG,EAAE,CAAC;CACtB;AAED,wBAAsB,aAAa,CACjC,aAAa,EAAE,aAAa,CAAC,SAAS,CAAC,EACvC,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CAuJvB"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
export async function computePareto(batchIterator, options = {}) {
|
|
2
|
+
let itemCol = options.itemCol;
|
|
3
|
+
let valueCol = options.valueCol;
|
|
4
|
+
const aThreshold = options.aThreshold ?? 80;
|
|
5
|
+
const bThreshold = options.bThreshold ?? 95;
|
|
6
|
+
const itemMap = new Map();
|
|
7
|
+
for await (const batch of batchIterator) {
|
|
8
|
+
if (batch.rows.length === 0)
|
|
9
|
+
continue;
|
|
10
|
+
if (!itemCol || !valueCol) {
|
|
11
|
+
const firstRow = batch.rows[0];
|
|
12
|
+
const keys = Object.keys(firstRow);
|
|
13
|
+
if (!itemCol) {
|
|
14
|
+
itemCol =
|
|
15
|
+
keys.find((k) => /^(item|product|sku|category|customer|name|title|key|id)$/i.test(k)) ??
|
|
16
|
+
keys[0];
|
|
17
|
+
}
|
|
18
|
+
if (!valueCol) {
|
|
19
|
+
valueCol =
|
|
20
|
+
keys.find((k) => /(value|revenue|sales|amount|total|spend|count|qty|quantity|price)/i.test(k)) ??
|
|
21
|
+
keys[1];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
for (const row of batch.rows) {
|
|
25
|
+
const rawItem = row[itemCol];
|
|
26
|
+
if (rawItem === null || rawItem === undefined || rawItem === "")
|
|
27
|
+
continue;
|
|
28
|
+
const it = String(rawItem);
|
|
29
|
+
const rawVal = row[valueCol];
|
|
30
|
+
let numVal = 0;
|
|
31
|
+
if (typeof rawVal === "number") {
|
|
32
|
+
numVal = rawVal;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
const parsed = parseFloat(String(rawVal));
|
|
36
|
+
if (!isNaN(parsed))
|
|
37
|
+
numVal = parsed;
|
|
38
|
+
}
|
|
39
|
+
itemMap.set(it, (itemMap.get(it) || 0) + numVal);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const sortedList = Array.from(itemMap.entries()).sort((a, b) => b[1] - a[1]);
|
|
43
|
+
const totalItems = sortedList.length;
|
|
44
|
+
let totalValue = 0;
|
|
45
|
+
for (const [, val] of sortedList) {
|
|
46
|
+
totalValue += val;
|
|
47
|
+
}
|
|
48
|
+
const items = [];
|
|
49
|
+
let runningSum = 0;
|
|
50
|
+
let pareto80Count = 0;
|
|
51
|
+
for (let rank = 1; rank <= totalItems; rank++) {
|
|
52
|
+
const [name, val] = sortedList[rank - 1];
|
|
53
|
+
runningSum += val;
|
|
54
|
+
const sharePct = totalValue > 0 ? (val / totalValue) * 100 : 0;
|
|
55
|
+
const cumPct = totalValue > 0 ? (runningSum / totalValue) * 100 : 0;
|
|
56
|
+
let abc = "C";
|
|
57
|
+
if (cumPct <= aThreshold || (rank === 1 && cumPct > aThreshold)) {
|
|
58
|
+
abc = "A";
|
|
59
|
+
}
|
|
60
|
+
else if (cumPct <= bThreshold) {
|
|
61
|
+
abc = "B";
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
abc = "C";
|
|
65
|
+
}
|
|
66
|
+
if (cumPct <= 80 || (pareto80Count === 0 && cumPct > 80)) {
|
|
67
|
+
pareto80Count = rank;
|
|
68
|
+
}
|
|
69
|
+
items.push({
|
|
70
|
+
rank,
|
|
71
|
+
item: name,
|
|
72
|
+
value: Math.round(val * 100) / 100,
|
|
73
|
+
share_pct: Math.round(sharePct * 100) / 100,
|
|
74
|
+
cumulative_value: Math.round(runningSum * 100) / 100,
|
|
75
|
+
cumulative_pct: Math.round(cumPct * 10) / 10,
|
|
76
|
+
abc_class: abc,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
// Calculate Summary Categories
|
|
80
|
+
const classA = items.filter((it) => it.abc_class === "A");
|
|
81
|
+
const classB = items.filter((it) => it.abc_class === "B");
|
|
82
|
+
const classC = items.filter((it) => it.abc_class === "C");
|
|
83
|
+
const sumA = classA.reduce((acc, it) => acc + it.value, 0);
|
|
84
|
+
const sumB = classB.reduce((acc, it) => acc + it.value, 0);
|
|
85
|
+
const sumC = classC.reduce((acc, it) => acc + it.value, 0);
|
|
86
|
+
const summary = [
|
|
87
|
+
{
|
|
88
|
+
abc_class: "A",
|
|
89
|
+
item_count: classA.length,
|
|
90
|
+
item_percentage: totalItems > 0 ? Math.round((classA.length / totalItems) * 1000) / 10 : 0,
|
|
91
|
+
total_value: Math.round(sumA * 100) / 100,
|
|
92
|
+
value_percentage: totalValue > 0 ? Math.round((sumA / totalValue) * 1000) / 10 : 0,
|
|
93
|
+
description: "Vital Few: Top driving ~80% of value",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
abc_class: "B",
|
|
97
|
+
item_count: classB.length,
|
|
98
|
+
item_percentage: totalItems > 0 ? Math.round((classB.length / totalItems) * 1000) / 10 : 0,
|
|
99
|
+
total_value: Math.round(sumB * 100) / 100,
|
|
100
|
+
value_percentage: totalValue > 0 ? Math.round((sumB / totalValue) * 1000) / 10 : 0,
|
|
101
|
+
description: "Moderate: Intermediate ~15% of value",
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
abc_class: "C",
|
|
105
|
+
item_count: classC.length,
|
|
106
|
+
item_percentage: totalItems > 0 ? Math.round((classC.length / totalItems) * 1000) / 10 : 0,
|
|
107
|
+
total_value: Math.round(sumC * 100) / 100,
|
|
108
|
+
value_percentage: totalValue > 0 ? Math.round((sumC / totalValue) * 1000) / 10 : 0,
|
|
109
|
+
description: "Trivial Many: Long tail ~5% of value",
|
|
110
|
+
},
|
|
111
|
+
];
|
|
112
|
+
const pareto80Pct = totalItems > 0 ? Math.round((pareto80Count / totalItems) * 1000) / 10 : 0;
|
|
113
|
+
const formattedRows = options.summary
|
|
114
|
+
? summary.map((s) => ({
|
|
115
|
+
abc_class: s.abc_class,
|
|
116
|
+
items: `${s.item_count} (${s.item_percentage.toFixed(1)}%)`,
|
|
117
|
+
total_value: s.total_value,
|
|
118
|
+
value_share: `${s.value_percentage.toFixed(1)}%`,
|
|
119
|
+
description: s.description,
|
|
120
|
+
}))
|
|
121
|
+
: items.map((it) => ({
|
|
122
|
+
rank: it.rank,
|
|
123
|
+
item: it.item,
|
|
124
|
+
value: it.value,
|
|
125
|
+
share: `${it.share_pct.toFixed(2)}%`,
|
|
126
|
+
cum_value: it.cumulative_value,
|
|
127
|
+
cum_share: `${it.cumulative_pct.toFixed(1)}%`,
|
|
128
|
+
class: it.abc_class,
|
|
129
|
+
}));
|
|
130
|
+
return {
|
|
131
|
+
items,
|
|
132
|
+
summary,
|
|
133
|
+
total_items: totalItems,
|
|
134
|
+
total_value: Math.round(totalValue * 100) / 100,
|
|
135
|
+
pareto_80_item_count: pareto80Count,
|
|
136
|
+
pareto_80_item_percentage: pareto80Pct,
|
|
137
|
+
formattedRows,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=pareto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pareto.js","sourceRoot":"","sources":["../../src/analytics/pareto.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DataStream } from "../core/types.js";
|
|
2
|
+
export interface QuantilesResult {
|
|
3
|
+
column: string;
|
|
4
|
+
count: number;
|
|
5
|
+
min: number;
|
|
6
|
+
max: number;
|
|
7
|
+
mean: number;
|
|
8
|
+
median: number;
|
|
9
|
+
q1: number;
|
|
10
|
+
q3: number;
|
|
11
|
+
iqr: number;
|
|
12
|
+
percentiles: Record<string, number>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Computes exact/interpolated percentiles from numeric stream.
|
|
16
|
+
*/
|
|
17
|
+
export declare function computeQuantiles(stream: DataStream, column: string, requestedPercentiles?: number[]): Promise<QuantilesResult>;
|
|
18
|
+
//# sourceMappingURL=quantiles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quantiles.d.ts","sourceRoot":"","sources":["../../src/analytics/quantiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EACd,oBAAoB,GAAE,MAAM,EAA6B,GACxD,OAAO,CAAC,eAAe,CAAC,CA8D1B"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Computes exact/interpolated percentiles from numeric stream.
|
|
3
|
+
*/
|
|
4
|
+
export async function computeQuantiles(stream, column, requestedPercentiles = [25, 50, 75, 90, 95, 99]) {
|
|
5
|
+
const values = [];
|
|
6
|
+
let sum = 0;
|
|
7
|
+
for await (const batch of stream) {
|
|
8
|
+
for (const row of batch.rows) {
|
|
9
|
+
const rawVal = row[column];
|
|
10
|
+
if (rawVal === null || rawVal === undefined || rawVal === "")
|
|
11
|
+
continue;
|
|
12
|
+
const num = typeof rawVal === "number" ? rawVal : parseFloat(String(rawVal));
|
|
13
|
+
if (Number.isFinite(num)) {
|
|
14
|
+
values.push(num);
|
|
15
|
+
sum += num;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (values.length === 0) {
|
|
20
|
+
throw new Error(`No numeric values found in column: "${column}"`);
|
|
21
|
+
}
|
|
22
|
+
// Sort values
|
|
23
|
+
values.sort((a, b) => a - b);
|
|
24
|
+
const n = values.length;
|
|
25
|
+
const mean = sum / n;
|
|
26
|
+
const min = values[0];
|
|
27
|
+
const max = values[n - 1];
|
|
28
|
+
function getPercentile(p) {
|
|
29
|
+
if (p <= 0)
|
|
30
|
+
return min;
|
|
31
|
+
if (p >= 100)
|
|
32
|
+
return max;
|
|
33
|
+
const rank = (p / 100) * (n - 1);
|
|
34
|
+
const low = Math.floor(rank);
|
|
35
|
+
const high = Math.ceil(rank);
|
|
36
|
+
const weight = rank - low;
|
|
37
|
+
return values[low] * (1 - weight) + values[high] * weight;
|
|
38
|
+
}
|
|
39
|
+
const q1 = getPercentile(25);
|
|
40
|
+
const median = getPercentile(50);
|
|
41
|
+
const q3 = getPercentile(75);
|
|
42
|
+
const iqr = q3 - q1;
|
|
43
|
+
const percentiles = {};
|
|
44
|
+
const allPs = Array.from(new Set([...requestedPercentiles, 25, 50, 75])).sort((a, b) => a - b);
|
|
45
|
+
for (const p of allPs) {
|
|
46
|
+
const key = `p${p}`;
|
|
47
|
+
percentiles[key] = parseFloat(getPercentile(p).toFixed(4));
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
column,
|
|
51
|
+
count: n,
|
|
52
|
+
min,
|
|
53
|
+
max,
|
|
54
|
+
mean: parseFloat(mean.toFixed(4)),
|
|
55
|
+
median: parseFloat(median.toFixed(4)),
|
|
56
|
+
q1: parseFloat(q1.toFixed(4)),
|
|
57
|
+
q3: parseFloat(q3.toFixed(4)),
|
|
58
|
+
iqr: parseFloat(iqr.toFixed(4)),
|
|
59
|
+
percentiles,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=quantiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quantiles.js","sourceRoot":"","sources":["../../src/analytics/quantiles.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DataStream } from "../core/types.js";
|
|
2
|
+
export interface LinearRegressionResult {
|
|
3
|
+
xColumn: string;
|
|
4
|
+
yColumn: string;
|
|
5
|
+
sampleSize: number;
|
|
6
|
+
slope: number;
|
|
7
|
+
intercept: number;
|
|
8
|
+
r: number;
|
|
9
|
+
r2: number;
|
|
10
|
+
stdError: number;
|
|
11
|
+
formula: string;
|
|
12
|
+
interpretation: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Computes Ordinary Least Squares (OLS) Linear Regression in a single pass.
|
|
16
|
+
*/
|
|
17
|
+
export declare function computeLinearRegression(stream: DataStream, xColumn: string, yColumn: string): Promise<LinearRegressionResult>;
|
|
18
|
+
//# sourceMappingURL=regression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regression.d.ts","sourceRoot":"","sources":["../../src/analytics/regression.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,sBAAsB,CAAC,CAkFjC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Computes Ordinary Least Squares (OLS) Linear Regression in a single pass.
|
|
3
|
+
*/
|
|
4
|
+
export async function computeLinearRegression(stream, xColumn, yColumn) {
|
|
5
|
+
let n = 0;
|
|
6
|
+
let meanX = 0;
|
|
7
|
+
let meanY = 0;
|
|
8
|
+
let m2X = 0;
|
|
9
|
+
let m2Y = 0;
|
|
10
|
+
let coMoment = 0;
|
|
11
|
+
for await (const batch of stream) {
|
|
12
|
+
for (const row of batch.rows) {
|
|
13
|
+
const rawX = row[xColumn];
|
|
14
|
+
const rawY = row[yColumn];
|
|
15
|
+
if (rawX === null || rawX === undefined || rawX === "")
|
|
16
|
+
continue;
|
|
17
|
+
if (rawY === null || rawY === undefined || rawY === "")
|
|
18
|
+
continue;
|
|
19
|
+
const x = typeof rawX === "number" ? rawX : parseFloat(String(rawX));
|
|
20
|
+
const y = typeof rawY === "number" ? rawY : parseFloat(String(rawY));
|
|
21
|
+
if (!Number.isFinite(x) || !Number.isFinite(y))
|
|
22
|
+
continue;
|
|
23
|
+
n++;
|
|
24
|
+
const dx = x - meanX;
|
|
25
|
+
meanX += dx / n;
|
|
26
|
+
const dy = y - meanY;
|
|
27
|
+
meanY += dy / n;
|
|
28
|
+
m2X += dx * (x - meanX);
|
|
29
|
+
m2Y += dy * (y - meanY);
|
|
30
|
+
coMoment += dx * (y - meanY);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (n < 2) {
|
|
34
|
+
throw new Error(`Insufficient numeric data points for regression (found ${n} pairs).`);
|
|
35
|
+
}
|
|
36
|
+
const varX = m2X / (n - 1);
|
|
37
|
+
const varY = m2Y / (n - 1);
|
|
38
|
+
const cov = coMoment / (n - 1);
|
|
39
|
+
if (varX === 0) {
|
|
40
|
+
throw new Error(`Independent variable (${xColumn}) has zero variance.`);
|
|
41
|
+
}
|
|
42
|
+
const slope = cov / varX;
|
|
43
|
+
const intercept = meanY - slope * meanX;
|
|
44
|
+
const stdX = Math.sqrt(varX);
|
|
45
|
+
const stdY = Math.sqrt(varY);
|
|
46
|
+
const r = stdY > 0 ? cov / (stdX * stdY) : 0;
|
|
47
|
+
const r2 = r * r;
|
|
48
|
+
// Residual sum of squares & std error
|
|
49
|
+
const ssTot = m2Y;
|
|
50
|
+
const ssReg = slope * slope * m2X;
|
|
51
|
+
const ssRes = Math.max(0, ssTot - ssReg);
|
|
52
|
+
const stdError = n > 2 ? Math.sqrt(ssRes / (n - 2)) : 0;
|
|
53
|
+
const sign = intercept >= 0 ? "+" : "-";
|
|
54
|
+
const absIntercept = Math.abs(intercept);
|
|
55
|
+
const formula = `${yColumn} = ${slope.toFixed(4)} * ${xColumn} ${sign} ${absIntercept.toFixed(4)}`;
|
|
56
|
+
let interpretation = "No linear relationship";
|
|
57
|
+
const absR = Math.abs(r);
|
|
58
|
+
if (absR >= 0.8)
|
|
59
|
+
interpretation = `Very strong ${r > 0 ? "positive" : "negative"} linear fit`;
|
|
60
|
+
else if (absR >= 0.6)
|
|
61
|
+
interpretation = `Strong ${r > 0 ? "positive" : "negative"} linear fit`;
|
|
62
|
+
else if (absR >= 0.4)
|
|
63
|
+
interpretation = `Moderate ${r > 0 ? "positive" : "negative"} linear fit`;
|
|
64
|
+
else if (absR >= 0.2)
|
|
65
|
+
interpretation = `Weak ${r > 0 ? "positive" : "negative"} linear fit`;
|
|
66
|
+
return {
|
|
67
|
+
xColumn,
|
|
68
|
+
yColumn,
|
|
69
|
+
sampleSize: n,
|
|
70
|
+
slope: parseFloat(slope.toFixed(6)),
|
|
71
|
+
intercept: parseFloat(intercept.toFixed(6)),
|
|
72
|
+
r: parseFloat(r.toFixed(4)),
|
|
73
|
+
r2: parseFloat(r2.toFixed(4)),
|
|
74
|
+
stdError: parseFloat(stdError.toFixed(4)),
|
|
75
|
+
formula,
|
|
76
|
+
interpretation,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=regression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regression.js","sourceRoot":"","sources":["../../src/analytics/regression.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { DataBatch } from "../core/types.js";
|
|
2
|
+
export interface RfmOptions {
|
|
3
|
+
customerIdCol?: string;
|
|
4
|
+
dateCol?: string;
|
|
5
|
+
amountCol?: string;
|
|
6
|
+
asOfDate?: string | Date;
|
|
7
|
+
}
|
|
8
|
+
export interface CustomerRfmRaw {
|
|
9
|
+
customerId: string;
|
|
10
|
+
lastDateMs: number;
|
|
11
|
+
frequency: number;
|
|
12
|
+
monetary: number;
|
|
13
|
+
}
|
|
14
|
+
export interface CustomerRfmResult {
|
|
15
|
+
customer_id: string;
|
|
16
|
+
recency_days: number;
|
|
17
|
+
frequency: number;
|
|
18
|
+
monetary: number;
|
|
19
|
+
r_score: number;
|
|
20
|
+
f_score: number;
|
|
21
|
+
m_score: number;
|
|
22
|
+
rfm_score: string;
|
|
23
|
+
segment: string;
|
|
24
|
+
}
|
|
25
|
+
export interface RfmSegmentSummary {
|
|
26
|
+
segment: string;
|
|
27
|
+
customer_count: number;
|
|
28
|
+
customer_percentage: number;
|
|
29
|
+
total_revenue: number;
|
|
30
|
+
revenue_percentage: number;
|
|
31
|
+
avg_recency_days: number;
|
|
32
|
+
avg_frequency: number;
|
|
33
|
+
avg_monetary: number;
|
|
34
|
+
}
|
|
35
|
+
export declare function classifyRfmSegment(r: number, f: number, m: number): string;
|
|
36
|
+
export declare function computeRfm(batchIterator: AsyncIterable<DataBatch>, options?: RfmOptions): Promise<{
|
|
37
|
+
customers: CustomerRfmResult[];
|
|
38
|
+
summary: RfmSegmentSummary[];
|
|
39
|
+
referenceDate: string;
|
|
40
|
+
}>;
|
|
41
|
+
//# sourceMappingURL=rfm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rfm.d.ts","sourceRoot":"","sources":["../../src/analytics/rfm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAO,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,WAAW,UAAU;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAiDD,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAY1E;AAED,wBAAsB,UAAU,CAC9B,aAAa,EAAE,aAAa,CAAC,SAAS,CAAC,EACvC,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC;IACT,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAuKD"}
|