Cumulative¶
Source: src/memframe/wrappers/analytix/cumulative.py
CumulativeWrapper is the public cumulative interface exposed through a
ContextManager. It provides pandas-expanding()-like running computations:
cumulative sum, product, minimum, maximum, mean, count, standard deviation,
and variance, each computed over a window ordered by a column you choose (or
the physical row order by default).
Users normally call cumulative methods directly on a dataset context returned by an upload operation:
cumulative is top-level (dataset.cumsum, not dataset.dt.*) — dt is
reserved for DateTimeWrapper.
The lower-level files are implementation details:
src/memframe/core/analytix/cumulative/builds and executes backend-specific SQL (base.pyholds the DuckDB-flavoured shared engine plus dialect hooks,postgres.py/clickhouse.pyoverride per backend,factory.pydispatchesmake_cumulative_ops(adapter)onisinstance).src/memframe/core/orchestrator/analytix/cumulative.pyresolves the active dataset context and passes persistence metadata.src/memframe/wrappers/analytix/cumulative.pyexposes synchronous and asynchronous public methods.
Public API¶
Every cumulative operation has synchronous and asynchronous forms. All take
(column, order_col=None, target_col=None):
| Synchronous | Asynchronous | Purpose |
|---|---|---|
cumsum(column, order_col=None, target_col=None) |
await acumsum(...) |
Running sum |
cumprod(column, order_col=None, target_col=None) |
await acumprod(...) |
Running product |
cummax(column, order_col=None, target_col=None) |
await acummax(...) |
Running maximum |
cummin(column, order_col=None, target_col=None) |
await acummin(...) |
Running minimum |
cummean(column, order_col=None, target_col=None) |
await acummean(...) |
Running mean |
cumcount(column, order_col=None, target_col=None) |
await acumcount(...) |
Running non-null count |
cumstd(column, order_col=None, target_col=None) |
await acumstd(...) |
Running population stddev |
cumvar(column, order_col=None, target_col=None) |
await acumvar(...) |
Running population variance |
Public methods return the resulting DataFrame directly. Invalid operations
raise OperationError.
Usage Overview¶
dataset = mf.upload_df(frame)
sample = dataset.cumsum("revenue", order_col="month")
sample = dataset.cummean("score", target_col="running_avg")
sample = dataset.cumcount("user_id")
dataset = await mf.aupload_df(frame)
sample = await dataset.acumsum("revenue", order_col="month")
sample = await dataset.acummean("score", target_col="running_avg")
order_col is optional — omit it to use physical row order:
sample = dataset.cumsum("revenue")
sample = dataset.cummean("score")
sample = dataset.cumcount("user_id")
Common Parameters¶
| Parameter | Type | Description |
|---|---|---|
column |
str |
Numeric column to accumulate. |
order_col |
str, list[str], or None |
Row ordering for the window. None (default) uses physical row order. A list orders by multiple columns. |
target_col |
str or None |
Name for the result column. Auto-generated as cum_<column>_<op> if omitted (e.g. cum_revenue_sum). |
order_col accepts a single column or a list:
result = dataset.cumsum("revenue", order_col="month")
result = dataset.cumsum("revenue", order_col=["region", "month"])
With no order_col, rows accumulate in physical storage order (PostgreSQL
ctid, DuckDB rowid). ClickHouse has no stable row id, so a synthetic
_ch_rowid (ROW_NUMBER() OVER()) is generated in a subquery to give the
window a deterministic order.
Running Sum and Product¶
cumsum¶
Running sum via SUM(col) OVER (ORDER BY … ROWS BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW).
Example x=[1.0, 2.0, 3.0] → cum_x_sum=[1.0, 3.0, 6.0].
cumprod¶
Running product via EXP(SUM(LN(NULLIF(col, 0))) OVER (…)). Zeros are
skipped rather than zeroing the tail (x=[2.0, 0.0, 4.0] →
cum_x_prod≈[2.0, 2.0, 8.0], floating-point dust applies).
Negative inputs abort the whole operation with is_error True (engines
reject LN of a negative — e.g. DuckDB's "cannot take logarithm of a
negative number"). Restrict cumprod to non-negative columns.
Running Min, Max, and Mean¶
cummax, cummin¶
Running extrema via MAX(col) / MIN(col) over the same window frame.
result = await dataset.acummax("price", order_col="day")
result = await dataset.acummin("price", order_col="day")
cummean¶
Running mean via AVG(col).
NULL values are ignored by the aggregation but still occupy a row, so a
NULL row repeats the previous running value (x=[2.0, 0.0, -3.0, NULL,
4.0] → cum_x_mean=[2.0, 1.0, -0.33, -0.33, 0.75]).
Running Count, Stddev, and Variance¶
cumcount¶
Running non-null count via COUNT(col). Unlike the other ops, NULL rows
do not advance the count (x=[2.0, 0.0, -3.0, NULL, 4.0] →
cum_x_count=[1, 2, 3, 3, 4]).
The result column is BIGINT on PostgreSQL/DuckDB and UInt64 on
ClickHouse.
cumstd, cumvar¶
Running population (not sample) statistics: STDDEV_POP(col) /
VAR_POP(col) on PostgreSQL and DuckDB, stddevPop(col) / varPop(col)
on ClickHouse.
result = dataset.cumstd("score", order_col="month")
result = dataset.cumvar("score", order_col="month")
result = await dataset.acumstd("score", order_col="month")
result = await dataset.acumvar("score", order_col="month")
A single-row frame yields 0.0 (population denominator n, not n-1).
Return Values and Errors¶
Public cumulative methods return the resulting DataFrame directly. Generated
table names and operation metadata remain internal to cache and AI layers.
Invalid operations raise OperationError. A negative column passed to
cumprod, or a missing column, surfaces this way.
Generated Tables¶
Every cumulative operation is non-destructive to the source upload table.
Each operation creates a new transient table (<table>__op_<n>) holding the
source rows plus the result column, then returns a sample of it:
- PostgreSQL / DuckDB: clone via
CREATE TABLE … AS SELECT *,ADD COLUMNfor the target, thenUPDATE … FROM (SELECT ctid/rowid, <window> AS val …) WHERE t.<rid> = s.<rid>. - ClickHouse: a single
CREATE TABLE … ENGINE = MergeTree() ORDER BY tuple() AS SELECT *, <window> AS <target> FROM …— the window is computed inline because asynchronousUPDATEmutations can return stale data.
Operations are recorded with deep_cache=True, so repeat calls replay the
persisted transient table instead of recomputing.
Backend Behavior¶
Cumulative supports DuckDB, PostgreSQL, and ClickHouse adapters:
- Identifiers are sanitized and quoted before SQL is generated.
order_colmay be a single column, a list, or omitted (physical order; synthetic_ch_rowidon ClickHouse).STDDEV_POP/VAR_POPmap to ClickHouse-nativestddevPop/varPop;cumcountmapsBIGINTtoUInt64on ClickHouse.- The per-backend SQL is locked by
tests/unit/test_cumulative_sql_fingerprint.py(24 scenarios × 3 backends).
Errors¶
Cumulative methods raise OperationError for backend or validation
failures:
cumprodon a column containing negatives fails the whole operation (LNof a negative is an engine error, not per-rowNULL).- Missing columns fail with the canonical error envelope.
- Unsupported backends raise
OperationError.
API Reference¶
memframe.wrappers.analytix.cumulative.CumulativeWrapper
¶
Bases: CumulativeOrchestrator
Wrapper around CumulativeOrchestrator with async/sync methods.
acumsum(column, order_col=None, target_col=None)
async
¶
Asynchronously compute cumulative sum over a column.
cumsum(column, order_col=None, target_col=None)
async
¶
Synchronously compute cumulative sum over a column.
acumprod(column, order_col=None, target_col=None)
async
¶
Asynchronously compute cumulative product over a column.
cumprod(column, order_col=None, target_col=None)
async
¶
Synchronously compute cumulative product over a column.
acummax(column, order_col=None, target_col=None)
async
¶
Asynchronously compute cumulative maximum over a column.
cummax(column, order_col=None, target_col=None)
async
¶
Synchronously compute cumulative maximum over a column.
acummin(column, order_col=None, target_col=None)
async
¶
Asynchronously compute cumulative minimum over a column.
cummin(column, order_col=None, target_col=None)
async
¶
Synchronously compute cumulative minimum over a column.
acummean(column, order_col=None, target_col=None)
async
¶
Asynchronously compute cumulative mean over a column.
cummean(column, order_col=None, target_col=None)
async
¶
Synchronously compute cumulative mean over a column.
acumcount(column, order_col=None, target_col=None)
async
¶
Asynchronously compute cumulative count over a column.
cumcount(column, order_col=None, target_col=None)
async
¶
Synchronously compute cumulative count over a column.
acumstd(column, order_col=None, target_col=None)
async
¶
Asynchronously compute cumulative standard deviation.
cumstd(column, order_col=None, target_col=None)
async
¶
Synchronously compute cumulative standard deviation.
acumvar(column, order_col=None, target_col=None)
async
¶
Asynchronously compute cumulative variance.
cumvar(column, order_col=None, target_col=None)
async
¶
Synchronously compute cumulative variance.