Window function implementations for datajure. Each function takes a column (dtype reader/vector) and returns a column of the same length. These are called per-partition by the expr compiler when processing :win AST nodes in window mode (:by + :set).
Window function implementations for datajure. Each function takes a column (dtype reader/vector) and returns a column of the same length. These are called per-partition by the expr compiler when processing :win AST nodes in window mode (:by + :set).
Binary operators supported by win/each-prior.
Binary operators supported by win/each-prior.
Maps op keywords to binary functions for use in win-scan.
Maps op keywords to binary functions for use in win-scan.
(win-bfill col)(win-bfill col opt)Backward-fill nil values with the next non-nil value (NOCB — the mirror of
win-fills). Trailing nils (after the last non-nil) remain nil. Takes the
same optional limit (bare number or {:limit n}) with the same partial-fill
semantics. NOCB-then-LOCF combos compose by nesting:
#dt/e (win/fills (win/bfill :x)).
[nil 1 nil nil 4] -> [1 1 4 4 4]
Backward-fill nil values with the next non-nil value (NOCB — the mirror of
[[win-fills]]). Trailing nils (after the last non-nil) remain nil. Takes the
same optional limit (bare number or {:limit n}) with the same partial-fill
semantics. NOCB-then-LOCF combos compose by nesting:
#dt/e (win/fills (win/bfill :x)).
[nil 1 nil nil 4] -> [1 1 4 4 4](win-cummax col)Cumulative maximum. nil values skipped. Leading nils remain nil. [nil nil 5.0 8.0] -> [nil nil 5.0 8.0]
Cumulative maximum. nil values skipped. Leading nils remain nil. [nil nil 5.0 8.0] -> [nil nil 5.0 8.0]
(win-cummean col)Cumulative mean. nil values skipped. [10 20 30] -> [10.0 15.0 20.0]
Cumulative mean. nil values skipped. [10 20 30] -> [10.0 15.0 20.0]
(win-cummin col)Cumulative minimum. nil values skipped. Leading nils remain nil. [nil nil 5.0 3.0] -> [nil nil 5.0 3.0]
Cumulative minimum. nil values skipped. Leading nils remain nil. [nil nil 5.0 3.0] -> [nil nil 5.0 3.0]
(win-cumsum col)Cumulative sum. nil values treated as 0. [10 20 30] -> [10 30 60] [nil 20 30] -> [0.0 20.0 50.0]
Cumulative sum. nil values treated as 0. [10 20 30] -> [10 30 60] [nil 20 30] -> [0.0 20.0 50.0]
(win-delta col)Difference from previous element: x[i] - x[i-1]. Returns nil for the first element (no predecessor). [10 20 30] -> [nil 10 10]
Difference from previous element: x[i] - x[i-1]. Returns nil for the first element (no predecessor). [10 20 30] -> [nil 10 10]
(win-dense-rank col)SQL DENSE_RANK(): 1-based, dense tie method, based on current row order. No gaps after ties. Pre-sorted [30 20 20 10] -> [1 2 2 3]
SQL DENSE_RANK(): 1-based, dense tie method, based on current row order. No gaps after ties. Pre-sorted [30 20 20 10] -> [1 2 2 3]
(win-differ col)Boolean: true where value differs from predecessor. First element always returns true (q convention — no predecessor to match). [A A B B A] -> [true false true false true]
Boolean: true where value differs from predecessor. First element always returns true (q convention — no predecessor to match). [A A B B A] -> [true false true false true]
(win-each-prior op-kw col)Apply a binary operator to (f x[i] x[i-1]) for each element. Returns nil for the first element (no predecessor). Nil propagates: if either x[i] or x[i-1] is nil, result is nil.
op-kw must be one of: :+ :- :* :div :max :min :> :< :>= :<= :=
Generalizes win/delta (op=:-) and win/ratio (op=:div), but without the double-casting of win/delta or the zero-guard of win/ratio. Use win/delta or win/ratio directly when those semantics are needed.
Examples: (win-each-prior :- [10.0 20.0 30.0]) -> [nil 10.0 10.0] (win-each-prior :div [10.0 20.0 30.0]) -> [nil 2.0 1.5] (win-each-prior :max [30.0 10.0 50.0]) -> [nil 30.0 50.0]
Apply a binary operator to (f x[i] x[i-1]) for each element. Returns nil for the first element (no predecessor). Nil propagates: if either x[i] or x[i-1] is nil, result is nil. op-kw must be one of: :+ :- :* :div :max :min :> :< :>= :<= := Generalizes win/delta (op=:-) and win/ratio (op=:div), but without the double-casting of win/delta or the zero-guard of win/ratio. Use win/delta or win/ratio directly when those semantics are needed. Examples: (win-each-prior :- [10.0 20.0 30.0]) -> [nil 10.0 10.0] (win-each-prior :div [10.0 20.0 30.0]) -> [nil 2.0 1.5] (win-each-prior :max [30.0 10.0 50.0]) -> [nil 30.0 50.0]
(win-ema col period-or-alpha)Exponential moving average. The smoothing parameter accepts three forms:
{:alpha a} sets alpha directly, or {:period p} sets it via
the period formula — self-documenting alternatives to the
implicit numeric dispatch.
Seeded at first non-nil value. nil values carry forward last EMA.
Leading nils remain nil.
ema 2 [10 20 30] -> [10.0 16.67 25.56]
ema {:alpha 0.18} [10 …] -> same as ema 0.18 …Exponential moving average. The smoothing parameter accepts three forms:
- a number >= 1 → treated as period, alpha = 2 / (1 + period)
- a number < 1 → treated directly as smoothing factor alpha
- an options map → `{:alpha a}` sets alpha directly, or `{:period p}` sets it via
the period formula — self-documenting alternatives to the
implicit numeric dispatch.
Seeded at first non-nil value. nil values carry forward last EMA.
Leading nils remain nil.
ema 2 [10 20 30] -> [10.0 16.67 25.56]
ema {:alpha 0.18} [10 …] -> same as ema 0.18 …(win-fills col)(win-fills col opt)Forward-fill nil values with the last non-nil value. Leading nils (before the first non-nil) remain nil. Matches q's fills convention.
An optional limit — a bare number or {:limit n} — carries the value at most
n positions into each nil run, leaving the rest of the run nil (partial
fill: pandas ffill(limit=n) / mbmisc h.locf; deliberately NOT zoo's
all-or-nothing maxgap). Default: unlimited.
[1 nil nil 4 nil] -> [1 1 1 4 4] [1 nil nil 4 nil] {:limit 1} -> [1 1 nil 4 4]
Forward-fill nil values with the last non-nil value.
Leading nils (before the first non-nil) remain nil.
Matches q's fills convention.
An optional limit — a bare number or {:limit n} — carries the value at most
n positions into each nil run, leaving the rest of the run nil (partial
fill: pandas `ffill(limit=n)` / mbmisc `h.locf`; deliberately NOT zoo's
all-or-nothing `maxgap`). Default: unlimited.
[1 nil nil 4 nil] -> [1 1 1 4 4]
[1 nil nil 4 nil] {:limit 1} -> [1 1 nil 4 4](win-grr col)Inverse-hyperbolic-sine growth (mbmisc grr with IHS=TRUE):
asinh(x[i]) - asinh(x[i-1]) over the current partition/order. nil for the
first element (no predecessor). A run of zeros has zero growth: when both
x[i] and x[i-1] are 0, the result is 0.0 (not asinh(0)-asinh(0)). A nil or
non-finite operand yields nil.
[1 2 3] -> [nil (- (asinh 2) (asinh 1)) (- (asinh 3) (asinh 2))] [0 0 5] -> [nil 0.0 (- (asinh 5) (asinh 0))]
Inverse-hyperbolic-sine growth (mbmisc `grr` with IHS=TRUE): asinh(x[i]) - asinh(x[i-1]) over the current partition/order. nil for the first element (no predecessor). A run of zeros has zero growth: when both x[i] and x[i-1] are 0, the result is 0.0 (not asinh(0)-asinh(0)). A nil or non-finite operand yields nil. [1 2 3] -> [nil (- (asinh 2) (asinh 1)) (- (asinh 3) (asinh 2))] [0 0 5] -> [nil 0.0 (- (asinh 5) (asinh 0))]
(win-lag col offset)(win-lag col offset opts)Lag by offset positions. Boundary positions (no history) are nil, or the :fill
value from a trailing options map. Source nils that get lagged stay nil.
[10 20 30 40], offset=1 -> [nil 10 20 30]
[10 20 30 40], offset=1 {:fill 0} -> [0 10 20 30]
Lag by offset positions. Boundary positions (no history) are nil, or the `:fill`
value from a trailing options map. Source nils that get lagged stay nil.
[10 20 30 40], offset=1 -> [nil 10 20 30]
[10 20 30 40], offset=1 {:fill 0} -> [0 10 20 30](win-lead col offset)(win-lead col offset opts)Lead by offset positions. Boundary positions (no future) are nil, or the :fill
value from a trailing options map. Source nils that get led stay nil.
[10 20 30 40], offset=1 -> [20 30 40 nil]
[10 20 30 40], offset=1 {:fill 0} -> [20 30 40 0]
Lead by offset positions. Boundary positions (no future) are nil, or the `:fill`
value from a trailing options map. Source nils that get led stay nil.
[10 20 30 40], offset=1 -> [20 30 40 nil]
[10 20 30 40], offset=1 {:fill 0} -> [20 30 40 0](win-mavg col width)(win-mavg col width opts)Moving average over width rows (expanding at start). nil values skipped.
Matches q's mavg convention. Optional opts map: {:min-periods n} requires an
n-row window before emitting (e.g. width for a non-expanding R-style window).
3 mavg [10 20 30 40 50] -> [10.0 15.0 20.0 30.0 40.0]
Moving average over width rows (expanding at start). nil values skipped.
Matches q's mavg convention. Optional opts map: `{:min-periods n}` requires an
n-row window before emitting (e.g. `width` for a non-expanding R-style window).
3 mavg [10 20 30 40 50] -> [10.0 15.0 20.0 30.0 40.0](win-mdev col width)(win-mdev col width opt)Moving standard deviation over width rows (expanding at start). ddof (delta
degrees of freedom) sets the divisor n - ddof:
ddof=1 (default) — sample sd, matching R's sd and datajure's sd aggregator;
ddof=0 — population sd, matching q's mdev.
nil values skipped. A window with n <= ddof finite values yields nil (sample sd
of a single value is undefined, like R's sd).
The optional 3rd arg is either a bare ddof (back-compat) or an opts map
{:ddof d :min-periods n} (:min-periods default 1; width for a non-expanding
R sd/rollapplyr window).
3 mdev [10 20 30 40 50] -> [nil 7.071 10.0 10.0 10.0] (ddof=1, default)
3 mdev [10 20 30 40 50] 0 -> [0.0 5.0 8.165 8.165 8.165] (ddof=0, q's mdev)
Moving standard deviation over `width` rows (expanding at start). `ddof` (delta
degrees of freedom) sets the divisor `n - ddof`:
ddof=1 (default) — sample sd, matching R's `sd` and datajure's `sd` aggregator;
ddof=0 — population sd, matching q's `mdev`.
nil values skipped. A window with `n <= ddof` finite values yields nil (sample sd
of a single value is undefined, like R's `sd`).
The optional 3rd arg is either a bare `ddof` (back-compat) or an opts map
`{:ddof d :min-periods n}` (`:min-periods` default 1; `width` for a non-expanding
R `sd`/`rollapplyr` window).
3 mdev [10 20 30 40 50] -> [nil 7.071 10.0 10.0 10.0] (ddof=1, default)
3 mdev [10 20 30 40 50] 0 -> [0.0 5.0 8.165 8.165 8.165] (ddof=0, q's mdev)(win-mdowndev col width)(win-mdowndev col width opts)Moving downside deviation over width rows (expanding at start), MAR=0:
sqrt(mean(min(r,0)^2)) over the finite values in each trailing window, with the
count of finite values as the denominator (PerformanceAnalytics
DownsideDeviation, method='full', na.rm). nil/NaN/±Inf are skipped; a window
with no finite values (empty / all-missing) yields nil — undefined, no data to
deviate from — a deliberate divergence from R's DownsideDeviation (which returns
0), matching datajure's nil-for-undefined philosophy. A window with finite values
but no downside returns 0.0. Optional opts map: {:min-periods n} (default 1;
width for a non-expanding R rollapplyr window — the roll-dd convention).
3 mdowndev [1.0 2.0 -2.0] -> [0.0 0.0 ~1.1547]
Moving downside deviation over `width` rows (expanding at start), MAR=0:
sqrt(mean(min(r,0)^2)) over the finite values in each trailing window, with the
count of finite values as the denominator (PerformanceAnalytics
DownsideDeviation, method='full', na.rm). nil/NaN/±Inf are skipped; a window
with no finite values (empty / all-missing) yields nil — undefined, no data to
deviate from — a deliberate divergence from R's DownsideDeviation (which returns
0), matching datajure's nil-for-undefined philosophy. A window with finite values
but no downside returns 0.0. Optional opts map: `{:min-periods n}` (default 1;
`width` for a non-expanding R `rollapplyr` window — the `roll-dd` convention).
3 mdowndev [1.0 2.0 -2.0] -> [0.0 0.0 ~1.1547](win-mmax col width)(win-mmax col width opts)Moving maximum over width rows (expanding at start). nil values skipped. Optional
opts map: {:min-periods n} (default 1; width for a non-expanding window).
3 mmax [30 10 50 20 40] -> [30.0 30.0 50.0 50.0 50.0]
Moving maximum over width rows (expanding at start). nil values skipped. Optional
opts map: `{:min-periods n}` (default 1; `width` for a non-expanding window).
3 mmax [30 10 50 20 40] -> [30.0 30.0 50.0 50.0 50.0](win-mmin col width)(win-mmin col width opts)Moving minimum over width rows (expanding at start). nil values skipped. Optional
opts map: {:min-periods n} (default 1; width for a non-expanding window).
3 mmin [30 10 50 20 40] -> [30.0 10.0 10.0 10.0 20.0]
Moving minimum over width rows (expanding at start). nil values skipped. Optional
opts map: `{:min-periods n}` (default 1; `width` for a non-expanding window).
3 mmin [30 10 50 20 40] -> [30.0 10.0 10.0 10.0 20.0](win-msum col width)(win-msum col width opts)Moving sum over width rows (expanding at start). nil values skipped. Optional
opts map: {:min-periods n} (default 1; width for a non-expanding window).
3 msum [10 20 30 40 50] -> [10.0 30.0 60.0 90.0 120.0]
Moving sum over width rows (expanding at start). nil values skipped. Optional
opts map: `{:min-periods n}` (default 1; `width` for a non-expanding window).
3 msum [10 20 30 40 50] -> [10.0 30.0 60.0 90.0 120.0](win-rank col)SQL RANK(): 1-based, min tie method, based on current row order. Ties (equal values) get the same rank, next rank skips. Pre-sorted [30 20 20 10] -> [1 2 2 4]
SQL RANK(): 1-based, min tie method, based on current row order. Ties (equal values) get the same rank, next rank skips. Pre-sorted [30 20 20 10] -> [1 2 2 4]
(win-ratio col)Ratio to previous element: x[i] / x[i-1].
Returns nil for the first element (no predecessor) and nil when the
previous element is zero (avoids Infinity propagation in financial data,
matching the div0 philosophy). The simple-return idiom
(- (win/ratio :price) 1) then yields nil for the observation after a
zero-price row, signalling 'exclude this observation' rather than
polluting downstream calculations with Infinity.
[10 20 30] -> [nil 2.0 1.5] [100 0 50 100] -> [nil 0.0 nil 2.0]
Ratio to previous element: x[i] / x[i-1]. Returns nil for the first element (no predecessor) and nil when the previous element is zero (avoids Infinity propagation in financial data, matching the div0 philosophy). The simple-return idiom `(- (win/ratio :price) 1)` then yields nil for the observation after a zero-price row, signalling 'exclude this observation' rather than polluting downstream calculations with Infinity. [10 20 30] -> [nil 2.0 1.5] [100 0 50 100] -> [nil 0.0 nil 2.0]
(win-rleid col)Run-length encoding group ID. Increments when value changes. [A A A B B A A] -> [1 1 1 2 2 3 3]
Run-length encoding group ID. Increments when value changes. [A A A B B A A] -> [1 1 1 2 2 3 3]
(win-row-number col)SQL ROW_NUMBER(): 1-based sequential numbering by current row order.
SQL ROW_NUMBER(): 1-based sequential numbering by current row order.
(win-scan op-kw col)Generalized cumulative scan: applies a binary op left-to-right across col (like Clojure's reductions). Nil values are skipped (last good value carried). Leading nils remain nil until first non-nil value is found.
op-kw must be one of :+ :* :max :min. Killer use case: cumulative compounding wealth index via :*
Examples: win-scan :+ [1 2 3 4] -> [1 3 6 10] win-scan :* [1.1 1.2 1.3] -> [1.1 1.32 1.716] win-scan :max [30 10 50 20] -> [30 30 50 50]
Generalized cumulative scan: applies a binary op left-to-right across col (like Clojure's reductions). Nil values are skipped (last good value carried). Leading nils remain nil until first non-nil value is found. op-kw must be one of :+ :* :max :min. Killer use case: cumulative compounding wealth index via :* Examples: win-scan :+ [1 2 3 4] -> [1 3 6 10] win-scan :* [1.1 1.2 1.3] -> [1.1 1.32 1.716] win-scan :max [30 10 50 20] -> [30 30 50 50]
(win-tlag col date-col)(win-tlag col date-col shift)(win-tlag col date-col shift opts)Date-value-aware lag (mbmisc lbd / statar tlag): row i gets the value of
col at the row whose date-col equals date[i] minus shift periods — nil
when no such row exists. Unlike the positional win/lag, a gap in the panel
yields nil instead of silently reaching back to the wrong period. A negative
shift is a lead. shift defaults to 1.
date-col values may be numbers (plain subtraction — years, xbar buckets,
encoded periods) or java.time temporals, shifted per the :unit option
(:day default, :week, :month, :quarter, :year). Exact-match caveat:
calendar arithmetic must land on a date present in the data — for monthly
panels keyed on month-END dates, tlag on a normalised month column (e.g. an
xbar bucket) rather than the raw date.
Dates must be unique within the partition (aggregate duplicates first, e.g.
:agg by the keys); duplicates throw a structured :tlag-duplicate-dates
error. nil dates yield nil and are never matched against.
#dt/e: (win/tlag :x :year) / (win/tlag :ret :date 1 {:unit :month})
Date-value-aware lag (mbmisc `lbd` / statar `tlag`): row i gets the value of
`col` at the row whose `date-col` equals date[i] minus `shift` periods — nil
when no such row exists. Unlike the positional `win/lag`, a gap in the panel
yields nil instead of silently reaching back to the wrong period. A negative
`shift` is a lead. `shift` defaults to 1.
`date-col` values may be numbers (plain subtraction — years, xbar buckets,
encoded periods) or java.time temporals, shifted per the `:unit` option
(`:day` default, `:week`, `:month`, `:quarter`, `:year`). Exact-match caveat:
calendar arithmetic must land on a date present in the data — for monthly
panels keyed on month-END dates, tlag on a normalised month column (e.g. an
`xbar` bucket) rather than the raw date.
Dates must be unique within the partition (aggregate duplicates first, e.g.
`:agg` by the keys); duplicates throw a structured :tlag-duplicate-dates
error. nil dates yield nil and are never matched against.
#dt/e: (win/tlag :x :year) / (win/tlag :ret :date 1 {:unit :month})cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |