pond-ts 0.22.0 → 0.24.0
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/CHANGELOG.md +125 -1
- package/README.md +18 -14
- package/dist/batch/aggregate-columns.d.ts +0 -24
- package/dist/batch/aggregate-columns.js +47 -32
- package/dist/batch/partitioned-time-series.d.ts +4 -20
- package/dist/batch/partitioned-time-series.js +25 -67
- package/dist/batch/time-series.d.ts +11 -20
- package/dist/batch/time-series.js +154 -15
- package/dist/batch/validate.js +2 -2
- package/dist/cjs-fallback.cjs +15 -0
- package/dist/index.d.ts +1 -1
- package/dist/live/live-aggregation.d.ts +2 -2
- package/dist/live/live-partitioned-series.d.ts +8 -31
- package/dist/live/live-rolling-aggregation.d.ts +2 -2
- package/dist/live/live-series.d.ts +5 -10
- package/dist/live/live-series.js +2 -1
- package/dist/live/live-view.d.ts +5 -10
- package/dist/live/live-view.js +1 -0
- package/dist/reducers/first.js +1 -0
- package/dist/reducers/last.js +1 -0
- package/dist/reducers/types.d.ts +16 -0
- package/dist/schema/aggregate.d.ts +162 -64
- package/dist/schema/events.d.ts +10 -0
- package/dist/schema/index.d.ts +1 -2
- package/dist/schema/index.js +8 -0
- package/dist/schema/reduce.d.ts +34 -4
- package/dist/schema/rolling.d.ts +1 -1
- package/package.json +4 -3
- package/dist/batch/aggregate-columns.d.ts.map +0 -1
- package/dist/batch/aggregate-columns.js.map +0 -1
- package/dist/batch/index.d.ts.map +0 -1
- package/dist/batch/index.js.map +0 -1
- package/dist/batch/json.d.ts.map +0 -1
- package/dist/batch/json.js.map +0 -1
- package/dist/batch/operators/collapse.d.ts.map +0 -1
- package/dist/batch/operators/collapse.js.map +0 -1
- package/dist/batch/operators/cumulative.d.ts.map +0 -1
- package/dist/batch/operators/cumulative.js.map +0 -1
- package/dist/batch/operators/diff-rate.d.ts.map +0 -1
- package/dist/batch/operators/diff-rate.js.map +0 -1
- package/dist/batch/operators/fill.d.ts.map +0 -1
- package/dist/batch/operators/fill.js.map +0 -1
- package/dist/batch/operators/map.d.ts.map +0 -1
- package/dist/batch/operators/map.js.map +0 -1
- package/dist/batch/operators/shift.d.ts.map +0 -1
- package/dist/batch/operators/shift.js.map +0 -1
- package/dist/batch/partitioned-time-series.d.ts.map +0 -1
- package/dist/batch/partitioned-time-series.js.map +0 -1
- package/dist/batch/time-series.d.ts.map +0 -1
- package/dist/batch/time-series.js.map +0 -1
- package/dist/batch/validate.d.ts.map +0 -1
- package/dist/batch/validate.js.map +0 -1
- package/dist/column.d.ts.map +0 -1
- package/dist/column.js.map +0 -1
- package/dist/columnar/array-column.d.ts.map +0 -1
- package/dist/columnar/array-column.js.map +0 -1
- package/dist/columnar/builder.d.ts.map +0 -1
- package/dist/columnar/builder.js.map +0 -1
- package/dist/columnar/chunked-column.d.ts.map +0 -1
- package/dist/columnar/chunked-column.js.map +0 -1
- package/dist/columnar/column.d.ts.map +0 -1
- package/dist/columnar/column.js.map +0 -1
- package/dist/columnar/concat.d.ts.map +0 -1
- package/dist/columnar/concat.js.map +0 -1
- package/dist/columnar/index.d.ts.map +0 -1
- package/dist/columnar/index.js.map +0 -1
- package/dist/columnar/key-column.d.ts.map +0 -1
- package/dist/columnar/key-column.js.map +0 -1
- package/dist/columnar/ring-buffer.d.ts.map +0 -1
- package/dist/columnar/ring-buffer.js.map +0 -1
- package/dist/columnar/scatter.d.ts.map +0 -1
- package/dist/columnar/scatter.js.map +0 -1
- package/dist/columnar/store.d.ts.map +0 -1
- package/dist/columnar/store.js.map +0 -1
- package/dist/columnar/string-column.d.ts.map +0 -1
- package/dist/columnar/string-column.js.map +0 -1
- package/dist/columnar/types.d.ts.map +0 -1
- package/dist/columnar/types.js.map +0 -1
- package/dist/columnar/validity.d.ts.map +0 -1
- package/dist/columnar/validity.js.map +0 -1
- package/dist/columnar/view.d.ts.map +0 -1
- package/dist/columnar/view.js.map +0 -1
- package/dist/core/calendar.d.ts.map +0 -1
- package/dist/core/calendar.js.map +0 -1
- package/dist/core/duration.d.ts.map +0 -1
- package/dist/core/duration.js.map +0 -1
- package/dist/core/errors.d.ts.map +0 -1
- package/dist/core/errors.js.map +0 -1
- package/dist/core/event.d.ts.map +0 -1
- package/dist/core/event.js.map +0 -1
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js.map +0 -1
- package/dist/core/interval.d.ts.map +0 -1
- package/dist/core/interval.js.map +0 -1
- package/dist/core/temporal.d.ts.map +0 -1
- package/dist/core/temporal.js.map +0 -1
- package/dist/core/time-range.d.ts.map +0 -1
- package/dist/core/time-range.js.map +0 -1
- package/dist/core/time.d.ts.map +0 -1
- package/dist/core/time.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/live/index.d.ts.map +0 -1
- package/dist/live/index.js.map +0 -1
- package/dist/live/live-aggregation.d.ts.map +0 -1
- package/dist/live/live-aggregation.js.map +0 -1
- package/dist/live/live-chunked-storage.d.ts.map +0 -1
- package/dist/live/live-chunked-storage.js.map +0 -1
- package/dist/live/live-fused-rolling.d.ts.map +0 -1
- package/dist/live/live-fused-rolling.js.map +0 -1
- package/dist/live/live-history.d.ts.map +0 -1
- package/dist/live/live-history.js.map +0 -1
- package/dist/live/live-partitioned-fused-rolling.d.ts.map +0 -1
- package/dist/live/live-partitioned-fused-rolling.js.map +0 -1
- package/dist/live/live-partitioned-series.d.ts.map +0 -1
- package/dist/live/live-partitioned-series.js.map +0 -1
- package/dist/live/live-partitioned-sync-rolling.d.ts.map +0 -1
- package/dist/live/live-partitioned-sync-rolling.js.map +0 -1
- package/dist/live/live-reduce.d.ts.map +0 -1
- package/dist/live/live-reduce.js.map +0 -1
- package/dist/live/live-rolling-aggregation.d.ts.map +0 -1
- package/dist/live/live-rolling-aggregation.js.map +0 -1
- package/dist/live/live-series.d.ts.map +0 -1
- package/dist/live/live-series.js.map +0 -1
- package/dist/live/live-storage.d.ts.map +0 -1
- package/dist/live/live-storage.js.map +0 -1
- package/dist/live/live-view.d.ts.map +0 -1
- package/dist/live/live-view.js.map +0 -1
- package/dist/live/series-store.d.ts.map +0 -1
- package/dist/live/series-store.js.map +0 -1
- package/dist/live/triggers.d.ts.map +0 -1
- package/dist/live/triggers.js.map +0 -1
- package/dist/reducers/avg.d.ts.map +0 -1
- package/dist/reducers/avg.js.map +0 -1
- package/dist/reducers/count.d.ts.map +0 -1
- package/dist/reducers/count.js.map +0 -1
- package/dist/reducers/difference.d.ts.map +0 -1
- package/dist/reducers/difference.js.map +0 -1
- package/dist/reducers/first.d.ts.map +0 -1
- package/dist/reducers/first.js.map +0 -1
- package/dist/reducers/index.d.ts.map +0 -1
- package/dist/reducers/index.js.map +0 -1
- package/dist/reducers/keep.d.ts.map +0 -1
- package/dist/reducers/keep.js.map +0 -1
- package/dist/reducers/last.d.ts.map +0 -1
- package/dist/reducers/last.js.map +0 -1
- package/dist/reducers/max.d.ts.map +0 -1
- package/dist/reducers/max.js.map +0 -1
- package/dist/reducers/median.d.ts.map +0 -1
- package/dist/reducers/median.js.map +0 -1
- package/dist/reducers/min.d.ts.map +0 -1
- package/dist/reducers/min.js.map +0 -1
- package/dist/reducers/percentile.d.ts.map +0 -1
- package/dist/reducers/percentile.js.map +0 -1
- package/dist/reducers/rolling.d.ts.map +0 -1
- package/dist/reducers/rolling.js.map +0 -1
- package/dist/reducers/samples.d.ts.map +0 -1
- package/dist/reducers/samples.js.map +0 -1
- package/dist/reducers/stdev.d.ts.map +0 -1
- package/dist/reducers/stdev.js.map +0 -1
- package/dist/reducers/sum.d.ts.map +0 -1
- package/dist/reducers/sum.js.map +0 -1
- package/dist/reducers/top.d.ts.map +0 -1
- package/dist/reducers/top.js.map +0 -1
- package/dist/reducers/types.d.ts.map +0 -1
- package/dist/reducers/types.js.map +0 -1
- package/dist/reducers/unique.d.ts.map +0 -1
- package/dist/reducers/unique.js.map +0 -1
- package/dist/schema/aggregate.d.ts.map +0 -1
- package/dist/schema/aggregate.js.map +0 -1
- package/dist/schema/diff.d.ts.map +0 -1
- package/dist/schema/diff.js.map +0 -1
- package/dist/schema/events.d.ts.map +0 -1
- package/dist/schema/events.js.map +0 -1
- package/dist/schema/index.d.ts.map +0 -1
- package/dist/schema/index.js.map +0 -1
- package/dist/schema/join.d.ts.map +0 -1
- package/dist/schema/join.js.map +0 -1
- package/dist/schema/json.d.ts.map +0 -1
- package/dist/schema/json.js.map +0 -1
- package/dist/schema/public.d.ts.map +0 -1
- package/dist/schema/public.js.map +0 -1
- package/dist/schema/reduce.d.ts.map +0 -1
- package/dist/schema/reduce.js.map +0 -1
- package/dist/schema/reshape.d.ts.map +0 -1
- package/dist/schema/reshape.js.map +0 -1
- package/dist/schema/rolling.d.ts.map +0 -1
- package/dist/schema/rolling.js.map +0 -1
- package/dist/schema/series.d.ts.map +0 -1
- package/dist/schema/series.js.map +0 -1
- package/dist/sequence/bounded-sequence.d.ts.map +0 -1
- package/dist/sequence/bounded-sequence.js.map +0 -1
- package/dist/sequence/index.d.ts.map +0 -1
- package/dist/sequence/index.js.map +0 -1
- package/dist/sequence/sample.d.ts.map +0 -1
- package/dist/sequence/sample.js.map +0 -1
- package/dist/sequence/sequence.d.ts.map +0 -1
- package/dist/sequence/sequence.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
7
7
|
file covers both packages. Pre-1.0: minor bumps may include new features and
|
|
8
8
|
type-level changes; patch bumps are strictly additive.
|
|
9
9
|
|
|
10
|
-
[Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.
|
|
10
|
+
[Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.24.0...HEAD
|
|
11
|
+
[0.24.0]: https://github.com/pjm17971/pond-ts/compare/v0.23.0...v0.24.0
|
|
12
|
+
[0.23.0]: https://github.com/pjm17971/pond-ts/compare/v0.22.0...v0.23.0
|
|
11
13
|
[0.22.0]: https://github.com/pjm17971/pond-ts/compare/v0.21.0...v0.22.0
|
|
12
14
|
[0.21.0]: https://github.com/pjm17971/pond-ts/compare/v0.20.0...v0.21.0
|
|
13
15
|
[0.20.0]: https://github.com/pjm17971/pond-ts/compare/v0.19.0...v0.20.0
|
|
@@ -16,6 +18,128 @@ type-level changes; patch bumps are strictly additive.
|
|
|
16
18
|
|
|
17
19
|
## [Unreleased]
|
|
18
20
|
|
|
21
|
+
## [0.24.0] — 2026-06-14
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **`TimeSeries.timeRange()` is now a columnar key-axis read instead of a
|
|
26
|
+
reduce over materialized events.** Behavior is unchanged, but the old
|
|
27
|
+
implementation materialized every `Event` on its first call — and because
|
|
28
|
+
`aggregate()` defaults its `range` to `series.timeRange()`, a one-shot
|
|
29
|
+
`aggregate()` paid full event materialization before the columnar fast
|
|
30
|
+
path could run, erasing the win. The new path reads the key column's
|
|
31
|
+
begin/end axis directly: O(1) for time-keyed series, a typed-array scan
|
|
32
|
+
for range/interval-keyed series, with no event materialization. Measured
|
|
33
|
+
on 1M rows: `timeRange()` itself ~407 ms → ~0.002 ms (time-keyed); cold
|
|
34
|
+
`aggregate()` with a defaulted range ~387 ms → ~6 ms (~63×). Every
|
|
35
|
+
`timeRange()` / `overlaps` / `contains` / `intersection` caller benefits.
|
|
36
|
+
(Audit v2 §3.3.)
|
|
37
|
+
- **`aggregate()` now takes the columnar fast path when a mapping mixes
|
|
38
|
+
numeric reducers with `first` / `last`.** Previously a single `first` or
|
|
39
|
+
`last` column (they have no numeric `reduceColumn`) bailed the entire call
|
|
40
|
+
to the row path. They now qualify via a boundary scan — the first/last
|
|
41
|
+
_defined_ cell, on any column kind. Behavior is unchanged. The big
|
|
42
|
+
beneficiary is **partitioned `aggregate`**, which auto-injects a `'first'`
|
|
43
|
+
reducer for the partition column and so was excluded from the fast path on
|
|
44
|
+
every call (audit v2 §3.2/§3.3). Measured on 1M rows, flat
|
|
45
|
+
`{ cpu: 'avg', host: 'first' }`: ~37.7 ms → ~4.8 ms (~7.8×); the
|
|
46
|
+
pure-numeric path is unchanged. (The remaining `partitionBy` materialization
|
|
47
|
+
cost is addressed separately by the columnar `partitionBy` split.)
|
|
48
|
+
- **`partitionBy(...)` now splits the columnar store directly instead of
|
|
49
|
+
materializing events.** `collect()` / the per-partition sugar methods
|
|
50
|
+
(`fill` / `diff` / `rolling` / …) and `toMap()` previously walked
|
|
51
|
+
`this.events` to bucket rows, then rebuilt each partition via `fromEvents`
|
|
52
|
+
(re-validating + re-packing) — silently re-paying the event-materialization
|
|
53
|
+
tax the columnar wave removed, and making `partitionBy(host).fill().collect()`
|
|
54
|
+
the #1 batch hotspot. They now group row indices off the store and gather
|
|
55
|
+
each partition via a zero-materialization columnar selection. Behavior is
|
|
56
|
+
unchanged (partition order, the `' undefined'` missing-key bucket, composite
|
|
57
|
+
keys, and declared `groups` all preserved). Measured on 100k rows / 64
|
|
58
|
+
partitions: `toMap()` ~389 → ~25 ns/row (~15×, no event materialization at
|
|
59
|
+
all); `diff().collect()` ~2×; `fill(hold).collect()` ~1.7× (the residual is
|
|
60
|
+
`TimeSeries.concat` still materializing to re-sort — a separate follow-up).
|
|
61
|
+
Declared-`groups` membership is validated by the same columnar scan, so that
|
|
62
|
+
path is materialization-free too (~331 → ~33 ns/row). **Behavior note:**
|
|
63
|
+
per-partition sub-series from `toMap()` / `apply()` now lazily materialize
|
|
64
|
+
their own `Event` objects rather than reusing the source's instances — cell
|
|
65
|
+
values are identical; only object identity differs (`collect()`, which
|
|
66
|
+
returns the source unchanged, is unaffected). (Audit v2 §3.2.)
|
|
67
|
+
|
|
68
|
+
## [0.23.0] — 2026-06-13
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
|
|
72
|
+
- **`new TimeSeries({ …, sort: true })` (and `TimeSeries.fromJSON`) sort rows by
|
|
73
|
+
key on construction.** Pond requires rows in non-decreasing key order and
|
|
74
|
+
throws otherwise; `sort: true` accepts unsorted input (messy CSVs, merged
|
|
75
|
+
sources) and sorts it for you instead of forcing a manual pre-sort. The sort
|
|
76
|
+
is **stable** — rows with equal keys keep their input order — matching what
|
|
77
|
+
`TimeSeries.fromEvents` already does. The out-of-order error now names the
|
|
78
|
+
option. (Audit v2 §5 F3.)
|
|
79
|
+
|
|
80
|
+
### Changed
|
|
81
|
+
|
|
82
|
+
- **CommonJS consumers now get a clear error instead of
|
|
83
|
+
`ERR_PACKAGE_PATH_NOT_EXPORTED`.** Both `pond-ts` and `@pond-ts/react`
|
|
84
|
+
add a `require` condition to their `exports["."]` map pointing at a tiny
|
|
85
|
+
shipped CJS stub that throws an ESM-only message naming `import` as the
|
|
86
|
+
fix. The packages remain ES-module-only; this only improves the error a
|
|
87
|
+
`require('pond-ts')` caller sees. (Audit v2 §5 F6/F7/F9/F10/F11)
|
|
88
|
+
- **Published tarballs no longer ship `*.js.map` / `*.d.ts.map` source
|
|
89
|
+
maps.** The maps referenced a `../src` tree that was never included in
|
|
90
|
+
the tarball (`files: ["dist", …]`), so they were dead weight (~⅓ of the
|
|
91
|
+
unpacked size). A `prepack` step now strips them from the published
|
|
92
|
+
artifact for both packages; local `npm run build` still emits them, so
|
|
93
|
+
in-repo debugging is unaffected. (Audit v2 §5 F6/F7/F9/F10/F11)
|
|
94
|
+
|
|
95
|
+
### Fixed
|
|
96
|
+
|
|
97
|
+
- **Shipped `.d.ts` now type-check under `skipLibCheck: false`.** The internal
|
|
98
|
+
`EMITS_EVICT` marker symbol was `@internal` (stripped from the emitted
|
|
99
|
+
`series.d.ts`) but still referenced by un-stripped public declarations — a
|
|
100
|
+
by-name re-export in `schema/index.d.ts` and the `[EMITS_EVICT]` brand members
|
|
101
|
+
on `LiveSeries` / `LiveView` — leaving dangling references that broke strict
|
|
102
|
+
consumer builds with **TS2305**. Those references are now `@internal` too, so
|
|
103
|
+
the symbol is fully stripped from the published types; runtime behavior is
|
|
104
|
+
unchanged. (Audit v2 §5 F2.)
|
|
105
|
+
- **`TimeSeries.at(-1)` counts from the end**, matching `LiveSeries.at` and
|
|
106
|
+
`Array.prototype.at` (it previously returned `undefined` for any negative
|
|
107
|
+
index). Deep underflow (e.g. `at(-100)` on a 3-event series) still returns
|
|
108
|
+
`undefined`, and the non-integer / `NaN` guard is unchanged. (Audit v2 §5 F8.)
|
|
109
|
+
- **Docs: corrected `Time.asString()` (does not exist), the missing
|
|
110
|
+
`aggregate`/`materialize` → `pivotByGroup` rekey pointer, and an
|
|
111
|
+
inaccurate `rolling().value()` return-type example.** The getting-started
|
|
112
|
+
example now calls `event.key().toDate().toISOString()`; the aggregation
|
|
113
|
+
and reshape pages note that interval-keyed output must be rekeyed with
|
|
114
|
+
`.asTime({ at: 'begin' })` before a time-keyed transform like
|
|
115
|
+
`pivotByGroup` (whose runtime error now says so too); the rolling page
|
|
116
|
+
documents `value()` as `Record<string, ColumnValue | undefined>`.
|
|
117
|
+
(Audit v2 §5 F6/F7/F9/F10/F11)
|
|
118
|
+
- **Mixed shorthand + `{ from, using }` mappings now keep every output
|
|
119
|
+
column in the result type (Audit v2 §5 F1).** Calling
|
|
120
|
+
`aggregate` / `rolling` / `reduce` with a mapping that mixes the
|
|
121
|
+
shorthand form (`cpu: 'avg'`) and the spec form
|
|
122
|
+
(`cpu_p95: { from: 'cpu', using: 'p95' }`) in one call — the
|
|
123
|
+
docs-blessed pattern — previously resolved to the shorthand overload
|
|
124
|
+
and **silently dropped every spec-keyed output column from the result
|
|
125
|
+
type** (`event.get('cpu_p95')` failed to compile with `TS2345`), even
|
|
126
|
+
though the runtime emitted the column. The two overloads
|
|
127
|
+
(`AggregateMap` shorthand + `AggregateOutputMap` spec) are now
|
|
128
|
+
collapsed into one unified mapping shape whose result schema dispatches
|
|
129
|
+
per output key, so all columns survive and each narrows to its
|
|
130
|
+
reducer's output kind. Runtime behavior is unchanged — this is a
|
|
131
|
+
types-only fix plus the tests that should have caught it.
|
|
132
|
+
- **The unified mapping keeps the shorthand compile-time guards.** A
|
|
133
|
+
shorthand reducer is still kind-checked against its source column
|
|
134
|
+
(`host: 'avg'` on a `string` column stays a compile error), and a bare
|
|
135
|
+
reducer on a key that is not a source column (`ghost: 'avg'` — a typo
|
|
136
|
+
the runtime rejects with "unknown source column") is now a compile
|
|
137
|
+
error too. Spec keys (`{ from, using }`) remain free output names.
|
|
138
|
+
Inline mapping literals get full validation; values pre-widened to
|
|
139
|
+
`AggregateMap<S>` and broad-schema (`TimeSeries<SeriesSchema>`)
|
|
140
|
+
callers keep the permissive shape. `AggregateOutputMap` is retained
|
|
141
|
+
as a back-compat alias of `AggregateMap`.
|
|
142
|
+
|
|
19
143
|
## [0.22.0] — 2026-06-12
|
|
20
144
|
|
|
21
145
|
### Changed
|
package/README.md
CHANGED
|
@@ -152,20 +152,24 @@ const points = series.sample({ reservoir: { size: 500 } }).toRows();
|
|
|
152
152
|
|
|
153
153
|
## Performance
|
|
154
154
|
|
|
155
|
-
pond-ts is
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
|
162
|
-
|
|
|
163
|
-
| **
|
|
164
|
-
| **
|
|
165
|
-
| **
|
|
166
|
-
| **Statistics** |
|
|
167
|
-
| **
|
|
168
|
-
| **
|
|
155
|
+
pond-ts is faster on **every** comparable operation, with no regressions —
|
|
156
|
+
a **~17x** geometric-mean speedup across the measurable ops, plus a handful
|
|
157
|
+
of transforms (`select` / `rename`) that are **effectively instant** (O(1)
|
|
158
|
+
column rebinds, below the timer's resolution). The advantage grows with data
|
|
159
|
+
size.
|
|
160
|
+
|
|
161
|
+
| Category | Speedup (N=16k) | Notes |
|
|
162
|
+
| ----------------- | ---------------------------------------------------- | --------------------------------------------- |
|
|
163
|
+
| **Rate** | ~120x | Single columnar walk vs Pipeline |
|
|
164
|
+
| **Fill** | 77–87x | Single columnar pass vs Pipeline per strategy |
|
|
165
|
+
| **Aggregation** | 57–82x | O(N+B) bucketing vs O(N×B) Pipeline |
|
|
166
|
+
| **Statistics** | 18–80x | Typed-array reduce vs ImmutableJS iteration |
|
|
167
|
+
| **Alignment** | 42x | Forward cursor vs repeated binary search |
|
|
168
|
+
| **Construction** | 13x | Columnar intake vs ImmutableJS wrapping |
|
|
169
|
+
| **Chained** | 8x | Derived constructors vs per-step Pipeline |
|
|
170
|
+
| **Transforms** | `select`/`rename` instant; `collapse` 30x; `map` ~4x | Column reshapes vs Pipeline |
|
|
171
|
+
| **Event access** | 6x | Array indexing vs ImmutableJS `get()` |
|
|
172
|
+
| **Serialization** | 4x | Lightweight columnar representation |
|
|
169
173
|
|
|
170
174
|
See the [full benchmark results](website/docs/reference/benchmarks.mdx)
|
|
171
175
|
for detailed numbers. Run locally:
|
|
@@ -34,30 +34,6 @@ export type AggregateColumnSpec = {
|
|
|
34
34
|
* same `mapping` shape produces the same schema.
|
|
35
35
|
*/
|
|
36
36
|
export declare function normalizeAggregateColumns<S extends SeriesSchema>(schema: S, mapping: AggregateMap<S> | AggregateOutputMap<S>): AggregateColumnSpec[];
|
|
37
|
-
/**
|
|
38
|
-
* **Phase 4.7 step 3B — columnar fast path for time-keyed `aggregate()`.**
|
|
39
|
-
* On sorted time-keyed data each bucket is a contiguous index range, so
|
|
40
|
-
* when every mapped column is a built-in numeric reducer with a
|
|
41
|
-
* `reduceColumn` fast path over a **packed `Float64Column`** source, each
|
|
42
|
-
* bucket reduces straight off the typed-array slice — skipping the
|
|
43
|
-
* `series.events` materialization and the per-cell `state.add` walk the
|
|
44
|
-
* row path pays. Reuses the shipped step-3A `reduceColumn` kernels
|
|
45
|
-
* (sum/min/max/avg 59–73×, stdev 35×, median/p95 3.4×) per bucket.
|
|
46
|
-
*
|
|
47
|
-
* Returns `null` — caller takes the unchanged row path — when any column
|
|
48
|
-
* doesn't qualify: a custom-function reducer, a reducer with no
|
|
49
|
-
* `reduceColumn` (`first` / `last` / `unique` / `top` / `samples`), or a
|
|
50
|
-
* non-numeric / chunked / missing source column. All-or-nothing per call
|
|
51
|
-
* keeps the bucket walk single-pass; mixed mappings fall back wholesale.
|
|
52
|
-
*
|
|
53
|
-
* `begins` is the key column's begin axis (sorted, identical row order to
|
|
54
|
-
* the value columns — both read straight off the store). Bucketing
|
|
55
|
-
* replicates the row path exactly: `cursor` carries across buckets, and a
|
|
56
|
-
* bucket owns `[start, scan)` where `begins[i] ∈ [bucket.begin,
|
|
57
|
-
* bucket.end)`. Empty buckets reduce an empty slice — the reducer's
|
|
58
|
-
* empty-input result (the step-3A parity contract guarantees this matches
|
|
59
|
-
* a zero-`add` bucket snapshot).
|
|
60
|
-
*/
|
|
61
37
|
export declare function tryAggregateColumnarTimeKeyed<B extends {
|
|
62
38
|
begin(): number;
|
|
63
39
|
end(): number;
|
|
@@ -73,45 +73,34 @@ export function normalizeAggregateColumns(schema, mapping) {
|
|
|
73
73
|
}
|
|
74
74
|
return normalized;
|
|
75
75
|
}
|
|
76
|
-
/**
|
|
77
|
-
* **Phase 4.7 step 3B — columnar fast path for time-keyed `aggregate()`.**
|
|
78
|
-
* On sorted time-keyed data each bucket is a contiguous index range, so
|
|
79
|
-
* when every mapped column is a built-in numeric reducer with a
|
|
80
|
-
* `reduceColumn` fast path over a **packed `Float64Column`** source, each
|
|
81
|
-
* bucket reduces straight off the typed-array slice — skipping the
|
|
82
|
-
* `series.events` materialization and the per-cell `state.add` walk the
|
|
83
|
-
* row path pays. Reuses the shipped step-3A `reduceColumn` kernels
|
|
84
|
-
* (sum/min/max/avg 59–73×, stdev 35×, median/p95 3.4×) per bucket.
|
|
85
|
-
*
|
|
86
|
-
* Returns `null` — caller takes the unchanged row path — when any column
|
|
87
|
-
* doesn't qualify: a custom-function reducer, a reducer with no
|
|
88
|
-
* `reduceColumn` (`first` / `last` / `unique` / `top` / `samples`), or a
|
|
89
|
-
* non-numeric / chunked / missing source column. All-or-nothing per call
|
|
90
|
-
* keeps the bucket walk single-pass; mixed mappings fall back wholesale.
|
|
91
|
-
*
|
|
92
|
-
* `begins` is the key column's begin axis (sorted, identical row order to
|
|
93
|
-
* the value columns — both read straight off the store). Bucketing
|
|
94
|
-
* replicates the row path exactly: `cursor` carries across buckets, and a
|
|
95
|
-
* bucket owns `[start, scan)` where `begins[i] ∈ [bucket.begin,
|
|
96
|
-
* bucket.end)`. Empty buckets reduce an empty slice — the reducer's
|
|
97
|
-
* empty-input result (the step-3A parity contract guarantees this matches
|
|
98
|
-
* a zero-`add` bucket snapshot).
|
|
99
|
-
*/
|
|
100
76
|
export function tryAggregateColumnarTimeKeyed(begins, getColumn, buckets, columns) {
|
|
101
77
|
const plans = [];
|
|
102
78
|
for (const spec of columns) {
|
|
103
79
|
if (typeof spec.reducer !== 'string')
|
|
104
80
|
return null; // custom function
|
|
105
81
|
const def = resolveReducer(spec.reducer);
|
|
106
|
-
if (def.reduceColumn === undefined)
|
|
107
|
-
return null; // first/last/unique/...
|
|
108
82
|
const source = getColumn(spec.source);
|
|
109
|
-
if (source === undefined
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
83
|
+
if (source === undefined)
|
|
84
|
+
return null; // missing source
|
|
85
|
+
if (def.definedBoundary !== undefined) {
|
|
86
|
+
// `first` / `last`: pick the first/last *defined* cell in the bucket
|
|
87
|
+
// via a boundary scan over any column kind / storage (`col.read(i)`).
|
|
88
|
+
// This is what lets a partitioned `aggregate` — whose auto-injected
|
|
89
|
+
// partition-column reducer is `'first'` — take the fast path instead
|
|
90
|
+
// of bailing the whole call for lack of a numeric `reduceColumn`.
|
|
91
|
+
plans.push({
|
|
92
|
+
kind: 'boundary',
|
|
93
|
+
column: source,
|
|
94
|
+
which: def.definedBoundary,
|
|
95
|
+
});
|
|
96
|
+
continue;
|
|
113
97
|
}
|
|
114
|
-
|
|
98
|
+
if (def.reduceColumn === undefined)
|
|
99
|
+
return null; // unique / top / samples / keep
|
|
100
|
+
if (source.kind !== 'number' || source.storage !== 'packed') {
|
|
101
|
+
return null; // non-numeric / chunked numeric source
|
|
102
|
+
}
|
|
103
|
+
plans.push({ kind: 'reduce', column: source, reduce: def.reduceColumn });
|
|
115
104
|
}
|
|
116
105
|
const n = begins.length;
|
|
117
106
|
let cursor = 0;
|
|
@@ -130,7 +119,33 @@ export function tryAggregateColumnarTimeKeyed(begins, getColumn, buckets, column
|
|
|
130
119
|
const reduced = new Array(plans.length);
|
|
131
120
|
for (let p = 0; p < plans.length; p += 1) {
|
|
132
121
|
const plan = plans[p];
|
|
133
|
-
|
|
122
|
+
if (plan.kind === 'reduce') {
|
|
123
|
+
reduced[p] = plan.reduce(plan.column.sliceByRange(start, scan));
|
|
124
|
+
}
|
|
125
|
+
else if (plan.which === 'first') {
|
|
126
|
+
// First defined cell in [start, scan); scans past missing cells.
|
|
127
|
+
let value;
|
|
128
|
+
for (let i = start; i < scan; i += 1) {
|
|
129
|
+
const cell = plan.column.read(i);
|
|
130
|
+
if (cell !== undefined) {
|
|
131
|
+
value = cell;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
reduced[p] = value;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
// Last defined cell in [start, scan); scans backward past missing.
|
|
139
|
+
let value;
|
|
140
|
+
for (let i = scan - 1; i >= start; i -= 1) {
|
|
141
|
+
const cell = plan.column.read(i);
|
|
142
|
+
if (cell !== undefined) {
|
|
143
|
+
value = cell;
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
reduced[p] = value;
|
|
148
|
+
}
|
|
134
149
|
}
|
|
135
150
|
rows[b] = Object.freeze([bucket, ...reduced]);
|
|
136
151
|
}
|
|
@@ -4,8 +4,7 @@ import { Sequence } from '../sequence/sequence.js';
|
|
|
4
4
|
import type { DurationInput } from '../core/duration.js';
|
|
5
5
|
import type { TemporalLike } from '../core/temporal.js';
|
|
6
6
|
import type { BatchSampleStrategy } from '../sequence/sample.js';
|
|
7
|
-
import type {
|
|
8
|
-
import type { AggregateOutputMapResultSchema, RollingOutputMapSchema } from '../schema/index.js';
|
|
7
|
+
import type { AggregateSchema, AlignSchema, BaselineSchema, DedupeKeep, DiffSchema, EventDataForSchema, FillMapping, FillStrategy, MaterializeSchema, NumericColumnNameForSchema, RollingAlignment, RollingSchema, SeriesSchema, SmoothAppendSchema, SmoothMethod, SmoothSchema, ValidatedAggregateMap } from '../schema/index.js';
|
|
9
8
|
type SequenceLike = Sequence | BoundedSequence;
|
|
10
9
|
type AlignMethod = 'hold' | 'linear';
|
|
11
10
|
type AlignSample = 'begin' | 'center' | 'end';
|
|
@@ -197,8 +196,6 @@ export declare class PartitionedTimeSeries<S extends SeriesSchema, K extends str
|
|
|
197
196
|
toMap(): Map<K, TimeSeries<S>>;
|
|
198
197
|
toMap<R extends SeriesSchema>(transform: (group: TimeSeries<S>) => TimeSeries<R>): Map<K, TimeSeries<R>>;
|
|
199
198
|
toMap<R>(transform: (group: TimeSeries<S>) => R): Map<K, R>;
|
|
200
|
-
private static partitionKeyOf;
|
|
201
|
-
private static bucketByPartition;
|
|
202
199
|
private static applyToSource;
|
|
203
200
|
private rewrap;
|
|
204
201
|
/**
|
|
@@ -247,26 +244,16 @@ export declare class PartitionedTimeSeries<S extends SeriesSchema, K extends str
|
|
|
247
244
|
range?: TemporalLike;
|
|
248
245
|
}): PartitionedTimeSeries<MaterializeSchema<S>, K>;
|
|
249
246
|
/** Per-partition `rolling`. See {@link TimeSeries.rolling}. */
|
|
250
|
-
rolling<const Mapping extends
|
|
247
|
+
rolling<const Mapping extends ValidatedAggregateMap<S, Mapping>>(window: DurationInput, mapping: Mapping, options?: {
|
|
251
248
|
alignment?: RollingAlignment;
|
|
252
249
|
minSamples?: number;
|
|
253
250
|
}): PartitionedTimeSeries<RollingSchema<S, Mapping>, K>;
|
|
254
|
-
rolling<const Mapping extends
|
|
255
|
-
alignment?: RollingAlignment;
|
|
256
|
-
minSamples?: number;
|
|
257
|
-
}): PartitionedTimeSeries<RollingOutputMapSchema<S, Mapping>, K>;
|
|
258
|
-
rolling<const Mapping extends AggregateMap<S>>(sequence: SequenceLike, window: DurationInput, mapping: Mapping, options?: {
|
|
251
|
+
rolling<const Mapping extends ValidatedAggregateMap<S, Mapping>>(sequence: SequenceLike, window: DurationInput, mapping: Mapping, options?: {
|
|
259
252
|
alignment?: RollingAlignment;
|
|
260
253
|
sample?: AlignSample;
|
|
261
254
|
range?: TemporalLike;
|
|
262
255
|
minSamples?: number;
|
|
263
256
|
}): PartitionedTimeSeries<AggregateSchema<S, Mapping>, K>;
|
|
264
|
-
rolling<const Mapping extends AggregateOutputMap<S>>(sequence: SequenceLike, window: DurationInput, mapping: Mapping, options?: {
|
|
265
|
-
alignment?: RollingAlignment;
|
|
266
|
-
sample?: AlignSample;
|
|
267
|
-
range?: TemporalLike;
|
|
268
|
-
minSamples?: number;
|
|
269
|
-
}): PartitionedTimeSeries<AggregateOutputMapResultSchema<S, Mapping>, K>;
|
|
270
257
|
/** Per-partition `smooth`. See {@link TimeSeries.smooth}. */
|
|
271
258
|
smooth<const Target extends NumericColumnNameForSchema<S>, const Output extends string | undefined = undefined>(column: Target, method: SmoothMethod, options: {
|
|
272
259
|
alpha: number;
|
|
@@ -319,12 +306,9 @@ export declare class PartitionedTimeSeries<S extends SeriesSchema, K extends str
|
|
|
319
306
|
/** Per-partition `shift`. See {@link TimeSeries.shift}. */
|
|
320
307
|
shift<const Target extends NumericColumnNameForSchema<S>>(columns: Target | readonly Target[], n: number): PartitionedTimeSeries<DiffSchema<S, Target>, K>;
|
|
321
308
|
/** Per-partition `aggregate`. See {@link TimeSeries.aggregate}. */
|
|
322
|
-
aggregate<const Mapping extends
|
|
309
|
+
aggregate<const Mapping extends ValidatedAggregateMap<S, Mapping>>(sequence: SequenceLike, mapping: Mapping, options?: {
|
|
323
310
|
range?: TemporalLike;
|
|
324
311
|
}): PartitionedTimeSeries<AggregateSchema<S, Mapping>, K>;
|
|
325
|
-
aggregate<const Mapping extends AggregateOutputMap<S>>(sequence: SequenceLike, mapping: Mapping, options?: {
|
|
326
|
-
range?: TemporalLike;
|
|
327
|
-
}): PartitionedTimeSeries<AggregateOutputMapResultSchema<S, Mapping>, K>;
|
|
328
312
|
}
|
|
329
313
|
export {};
|
|
330
314
|
//# sourceMappingURL=partitioned-time-series.d.ts.map
|
|
@@ -88,17 +88,17 @@ export class PartitionedTimeSeries {
|
|
|
88
88
|
this.validateGroupMembership();
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
// Validate that every
|
|
92
|
-
//
|
|
93
|
-
//
|
|
91
|
+
// Validate that every partition value appears in the declared groups.
|
|
92
|
+
// Scans the partition column columnar-natively via `_distinctPartitionKeys`
|
|
93
|
+
// (no event materialization — same encoding `toMap` produces), so the
|
|
94
|
+
// declared-`groups` path is materialization-free like the rest of the
|
|
95
|
+
// split.
|
|
94
96
|
validateGroupMembership() {
|
|
95
97
|
if (!this.groups)
|
|
96
98
|
return;
|
|
97
99
|
const col = this.by[0];
|
|
98
100
|
const declared = new Set(this.groups);
|
|
99
|
-
const
|
|
100
|
-
for (const event of this.source.events) {
|
|
101
|
-
const key = keyOf(event);
|
|
101
|
+
for (const key of this.source._distinctPartitionKeys(this.by)) {
|
|
102
102
|
if (!declared.has(key)) {
|
|
103
103
|
// Decode the encoder's leading-space sentinel so the message
|
|
104
104
|
// shows the user-facing concept, not the internal encoding.
|
|
@@ -205,96 +205,54 @@ export class PartitionedTimeSeries {
|
|
|
205
205
|
}
|
|
206
206
|
toMap(transform) {
|
|
207
207
|
const result = new Map();
|
|
208
|
-
|
|
208
|
+
// Columnar partition split — each sub-series is gathered straight off
|
|
209
|
+
// the store, no event materialization (the old path rebuilt every
|
|
210
|
+
// partition via `fromEvents`). Map order = first-encountered partition.
|
|
211
|
+
const partitions = this.source.length === 0
|
|
209
212
|
? new Map()
|
|
210
|
-
:
|
|
213
|
+
: this.source._partitionByColumns(this.by);
|
|
211
214
|
if (this.groups) {
|
|
212
215
|
// Declared-order iteration. Empty groups produce empty
|
|
213
216
|
// TimeSeries entries (consistent with pivotByGroup's typed
|
|
214
217
|
// groups behavior, which emits a column for every declared
|
|
215
218
|
// value even when no events match).
|
|
216
219
|
for (const g of this.groups) {
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
220
|
+
const sub = partitions.get(g) ??
|
|
221
|
+
TimeSeries.fromEvents([], {
|
|
222
|
+
schema: this.source.schema,
|
|
223
|
+
name: this.source.name,
|
|
224
|
+
});
|
|
222
225
|
result.set(g, transform ? transform(sub) : sub);
|
|
223
226
|
}
|
|
224
227
|
return result;
|
|
225
228
|
}
|
|
226
229
|
// Insertion-order iteration (matches the order each partition was
|
|
227
230
|
// first encountered in the source events).
|
|
228
|
-
for (const [key,
|
|
229
|
-
const sub = TimeSeries.fromEvents(events, {
|
|
230
|
-
schema: this.source.schema,
|
|
231
|
-
name: this.source.name,
|
|
232
|
-
});
|
|
231
|
+
for (const [key, sub] of partitions) {
|
|
233
232
|
result.set(key, transform ? transform(sub) : sub);
|
|
234
233
|
}
|
|
235
234
|
return result;
|
|
236
235
|
}
|
|
237
|
-
// Build the encoder that produces a string key for an event given
|
|
238
|
-
// the partition columns. Single-column case avoids the JSON encoding
|
|
239
|
-
// overhead. Multi-column uses JSON.stringify to guarantee no key
|
|
240
|
-
// collisions on values containing separators (e.g. region names with
|
|
241
|
-
// spaces) — a naive `parts.join('|')` would collide. `undefined` in a
|
|
242
|
-
// single-column key becomes the literal `' undefined'` (with the
|
|
243
|
-
// leading space ensuring it can never collide with a string column
|
|
244
|
-
// whose value is the literal `'undefined'`).
|
|
245
|
-
static partitionKeyOf(by) {
|
|
246
|
-
if (by.length === 1) {
|
|
247
|
-
const col = by[0];
|
|
248
|
-
return (event) => {
|
|
249
|
-
const v = event.data()[col];
|
|
250
|
-
return v === undefined ? ' undefined' : `${String(v)}`;
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
return (event) => {
|
|
254
|
-
const data = event.data();
|
|
255
|
-
const parts = new Array(by.length);
|
|
256
|
-
for (let i = 0; i < by.length; i += 1) {
|
|
257
|
-
parts[i] = data[by[i]] ?? null;
|
|
258
|
-
}
|
|
259
|
-
return JSON.stringify(parts);
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
// Group source events into buckets keyed by partition value. Returned
|
|
263
|
-
// Map iteration order = insertion order, which matches the order
|
|
264
|
-
// partitions were first seen in the source events array.
|
|
265
|
-
static bucketByPartition(source, by) {
|
|
266
|
-
const keyOf = PartitionedTimeSeries.partitionKeyOf(by);
|
|
267
|
-
const buckets = new Map();
|
|
268
|
-
for (const event of source.events) {
|
|
269
|
-
const key = keyOf(event);
|
|
270
|
-
let bucket = buckets.get(key);
|
|
271
|
-
if (!bucket) {
|
|
272
|
-
bucket = [];
|
|
273
|
-
buckets.set(key, bucket);
|
|
274
|
-
}
|
|
275
|
-
bucket.push(event);
|
|
276
|
-
}
|
|
277
|
-
return buckets;
|
|
278
|
-
}
|
|
279
236
|
// Internal helper used by both `apply` (terminal) and the sugar
|
|
280
237
|
// methods (which re-wrap the result back into a partitioned view).
|
|
281
238
|
static applyToSource(source, by, fn) {
|
|
282
239
|
// Empty source: apply fn to an empty group so the output schema
|
|
283
240
|
// and name come from fn, not from inferring R structurally.
|
|
284
|
-
if (source.
|
|
241
|
+
if (source.length === 0) {
|
|
285
242
|
const empty = TimeSeries.fromEvents([], {
|
|
286
243
|
schema: source.schema,
|
|
287
244
|
name: source.name,
|
|
288
245
|
});
|
|
289
246
|
return fn(empty);
|
|
290
247
|
}
|
|
291
|
-
|
|
248
|
+
// Columnar partition split — no event materialization. The old path
|
|
249
|
+
// walked `source.events` to bucket, then rebuilt each partition via
|
|
250
|
+
// `fromEvents` (re-validating + re-packing), silently re-paying the
|
|
251
|
+
// 495 ns/row tax the columnar wave removed. `_partitionByColumns`
|
|
252
|
+
// gathers each partition straight off the store (audit v2 §3.2).
|
|
253
|
+
const partitions = source._partitionByColumns(by);
|
|
292
254
|
const transformed = [];
|
|
293
|
-
for (const
|
|
294
|
-
const sub = TimeSeries.fromEvents(events, {
|
|
295
|
-
schema: source.schema,
|
|
296
|
-
name: source.name,
|
|
297
|
-
});
|
|
255
|
+
for (const sub of partitions.values()) {
|
|
298
256
|
transformed.push(fn(sub));
|
|
299
257
|
}
|
|
300
258
|
return TimeSeries.concat(transformed);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { AlignSchema, MaterializeSchema, ArrayAggregateAppendSchema, ArrayAggregateReplaceSchema, ArrayColumnNameForSchema, ArrayExplodeAppendSchema, ArrayExplodeReplaceSchema, BaselineSchema, AggregateReducer,
|
|
2
|
-
import type { AggregateOutputMapResultSchema, RollingOutputMapSchema } from '../schema/index.js';
|
|
1
|
+
import type { AlignSchema, MaterializeSchema, ArrayAggregateAppendSchema, ArrayAggregateReplaceSchema, ArrayColumnNameForSchema, ArrayExplodeAppendSchema, ArrayExplodeReplaceSchema, BaselineSchema, AggregateReducer, AggregateSchema, CollapseSchema, EventDataForSchema, EventForSchema, FirstColKind, IntervalKeyedSchema, JsonRowFormat, JoinManySchema, JoinSchema, JoinType, NumericColumnNameForSchema, NormalizedObjectRow, NormalizedRowForSchema, PivotByGroupSchema, PointRowForSchema, PrefixedJoinManySchema, PrefixedJoinSchema, ReduceResult, RenameMap, ValidatedAggregateMap } from '../schema/index.js';
|
|
3
2
|
import type { RenameSchema, RollingAlignment, RollingSchema, ColumnValue, DedupeKeep, DiffSchema, FillMapping, FillStrategy, ScalarKind, ScalarValue, SmoothMethod, SmoothAppendSchema, SmoothSchema, SelectSchema, SeriesSchema, TimeKeyedSchema, TimeSeriesJsonInput, TimeSeriesInput, TimeRangeKeyedSchema, ValueColumnKindForName, ValueColumnNameForSchema, ValueColumnsForSchema } from '../schema/index.js';
|
|
4
3
|
import { BoundedSequence } from '../sequence/bounded-sequence.js';
|
|
5
4
|
import { type TimeZoneOptions } from '../core/calendar.js';
|
|
@@ -77,6 +76,12 @@ export declare class TimeSeries<S extends SeriesSchema> {
|
|
|
77
76
|
*/
|
|
78
77
|
static fromJSON<S extends SeriesSchema>(input: TimeSeriesJsonInput<S> & {
|
|
79
78
|
parse?: TimeZoneOptions;
|
|
79
|
+
/**
|
|
80
|
+
* Sort rows by key before construction (off by default; see
|
|
81
|
+
* `TimeSeriesInput.sort`). Useful when reviving a wire payload whose
|
|
82
|
+
* rows aren't guaranteed sorted — avoids a manual pre-sort.
|
|
83
|
+
*/
|
|
84
|
+
sort?: boolean;
|
|
80
85
|
}): TimeSeries<S>;
|
|
81
86
|
/**
|
|
82
87
|
* Example: `TimeSeries.fromEvents(events, { schema, name })`.
|
|
@@ -497,12 +502,9 @@ export declare class TimeSeries<S extends SeriesSchema> {
|
|
|
497
502
|
* `series.partitionBy(col).aggregate(seq, mapping).collect()` to
|
|
498
503
|
* aggregate per entity. See {@link TimeSeries.partitionBy}.
|
|
499
504
|
*/
|
|
500
|
-
aggregate<const Mapping extends
|
|
505
|
+
aggregate<const Mapping extends ValidatedAggregateMap<S, Mapping>>(sequence: SequenceLike, mapping: Mapping, options?: {
|
|
501
506
|
range?: TemporalLike;
|
|
502
507
|
}): TimeSeries<AggregateSchema<S, Mapping>>;
|
|
503
|
-
aggregate<const Mapping extends AggregateOutputMap<S>>(sequence: SequenceLike, mapping: Mapping, options?: {
|
|
504
|
-
range?: TemporalLike;
|
|
505
|
-
}): TimeSeries<AggregateOutputMapResultSchema<S, Mapping>>;
|
|
506
508
|
/**
|
|
507
509
|
* Example: `series.reduce("value", "avg")`.
|
|
508
510
|
* Collapses the entire series to a single scalar value using the specified reducer.
|
|
@@ -516,8 +518,7 @@ export declare class TimeSeries<S extends SeriesSchema> {
|
|
|
516
518
|
* a plain value or record.
|
|
517
519
|
*/
|
|
518
520
|
reduce(column: ValueColumnsForSchema<S>[number]['name'], reducer: AggregateReducer): ColumnValue | undefined;
|
|
519
|
-
reduce<const Mapping extends
|
|
520
|
-
reduce<const Mapping extends AggregateOutputMap<S>>(mapping: Mapping): ReduceResult<S, Mapping>;
|
|
521
|
+
reduce<const Mapping extends ValidatedAggregateMap<S, Mapping>>(mapping: Mapping): ReduceResult<S, Mapping>;
|
|
521
522
|
/**
|
|
522
523
|
* Example: `series.groupBy("host")`.
|
|
523
524
|
* Partitions the series into groups keyed by the distinct values of a payload column.
|
|
@@ -900,26 +901,16 @@ export declare class TimeSeries<S extends SeriesSchema> {
|
|
|
900
901
|
* `series.partitionBy(col).rolling(...).collect()` to scope per
|
|
901
902
|
* entity. See {@link TimeSeries.partitionBy}.
|
|
902
903
|
*/
|
|
903
|
-
rolling<const Mapping extends
|
|
904
|
+
rolling<const Mapping extends ValidatedAggregateMap<S, Mapping>>(window: DurationInput, mapping: Mapping, options?: {
|
|
904
905
|
alignment?: RollingAlignment;
|
|
905
906
|
minSamples?: number;
|
|
906
907
|
}): TimeSeries<RollingSchema<S, Mapping>>;
|
|
907
|
-
rolling<const Mapping extends
|
|
908
|
-
alignment?: RollingAlignment;
|
|
909
|
-
minSamples?: number;
|
|
910
|
-
}): TimeSeries<RollingOutputMapSchema<S, Mapping>>;
|
|
911
|
-
rolling<const Mapping extends AggregateMap<S>>(sequence: SequenceLike, window: DurationInput, mapping: Mapping, options?: {
|
|
908
|
+
rolling<const Mapping extends ValidatedAggregateMap<S, Mapping>>(sequence: SequenceLike, window: DurationInput, mapping: Mapping, options?: {
|
|
912
909
|
alignment?: RollingAlignment;
|
|
913
910
|
sample?: AlignSample;
|
|
914
911
|
range?: TemporalLike;
|
|
915
912
|
minSamples?: number;
|
|
916
913
|
}): TimeSeries<AggregateSchema<S, Mapping>>;
|
|
917
|
-
rolling<const Mapping extends AggregateOutputMap<S>>(sequence: SequenceLike, window: DurationInput, mapping: Mapping, options?: {
|
|
918
|
-
alignment?: RollingAlignment;
|
|
919
|
-
sample?: AlignSample;
|
|
920
|
-
range?: TemporalLike;
|
|
921
|
-
minSamples?: number;
|
|
922
|
-
}): TimeSeries<AggregateOutputMapResultSchema<S, Mapping>>;
|
|
923
914
|
/**
|
|
924
915
|
* Example: `series.smooth("value", "ema", { alpha: 0.2 })`.
|
|
925
916
|
* Applies a smoothing transform to one numeric payload column while preserving the original key
|