core_lens.base.result#

Concrete, immutable result of a materialised View.

Classes#

Result

Concrete, immutable result of a materialised View.

Module Contents#

class core_lens.base.result.Result(data: polars.DataFrame | polars.LazyFrame, resolution: core_lens.schema.profile.Resolution, has_geometry: bool, key_cols: list[str], entity_name: str, entity: core_lens.base.entity.BaseEntity, metadata: dict[str, Any] | None = None)#

Concrete, immutable result of a materialised View.

Result is the shared output type for every entity and every materialisation path. It wraps a pl.LazyFrame, carries enough context to know how to re-attach geometry, and exposes compute methods that always return a fresh Result, keeping the chain composable:

result = aoi.mws.where(tehsil="Pangi").annual.between("2010-01-01", "2023-12-31")
mean_ndvi = result.aggregate(pl.mean("ndvi"), by="year")
mean_ndvi.plot.timeseries(x="year", y="ndvi")
Variables:
  • data – The underlying pl.LazyFrame. Use df() to materialise it into a pl.DataFrame. All compute methods produce a new Result whose data is the transformed frame.

  • metadata – Free-form dict populated by stats methods to carry method parameters (e.g. {"method": "pearson", "p_value": 0.003}). Empty on freshly materialised results.

  • resolution – A Resolution member (STATIC, ANNUAL, or SUB_ANNUAL). Used to validate which aggregate groupings are legal.

  • has_geometryTrue only for resolution="static" results and results on which with_geometry() has been called. When True, gdf() is available.

  • columns – Column names present in data at construction time. Snapshots the schema so callers can introspect without touching the frame.

  • key_cols – The entity’s key column(s) as carried from BaseEntity.

  • entity_name – Human-readable entity identifier (e.g. "mws").

  • entity – Reference to the parent entity, retained so with_geometry() can locate the static file without requiring callers to pass it again.

data#
resolution#
has_geometry#
columns: list[str]#
key_cols#
entity_name#
entity#
metadata: dict[str, Any]#
df() polars.DataFrame#

Return the underlying pl.DataFrame.

Returns:

The materialised data frame.

Return type:

pl.DataFrame

materialise() Result#

Evaluate the lazy computation graph and cache it in memory.

Returns:

A new Result with the data cached as an in-memory LazyFrame.

Return type:

Result

gdf() geopandas.GeoDataFrame#

Return the data as a GeoDataFrame.

Only valid when has_geometry is True. Use with_geometry() first on non-static results.

Returns:

A geopandas.GeoDataFrame built from data.

Return type:

gpd.GeoDataFrame

Raises:

TypeError – If has_geometry is False.

lazy() polars.LazyFrame#

Return a pl.LazyFrame for arbitrary further transformations.

This is an escape hatch for operations not covered by the Result API. The resulting LazyFrame is disconnected from Result — callers are responsible for collecting and wrapping the output themselves.

Returns:

A lazy frame backed by data.

Return type:

pl.LazyFrame

with_geometry() Result#

Return a new Result with the static geometry column joined in.

Reads only the key and geometry columns from the entity’s static file (no full scan), joins on key_cols, and returns a new Result with has_geometry=True.

This is the intended path for attaching coordinates to annual or sub_annual results before calling gdf() or result.plot.choropleth().

Returns:

A new Result with the geometry column merged in and has_geometry=True. If has_geometry is already True, returns self unchanged.

Return type:

Result

derive(name: str, expr: polars.Expr) Result#

Return a new Result with a computed column appended.

The derived column is a regular Polars column — no special tagging. It is fully chainable:

result.derive("ndwi", (pl.col("green") - pl.col("nir")) / (pl.col("green") + pl.col("nir")))
      .derive("drought_flag", pl.when(pl.col("rainfall") < 500).then(1).otherwise(0))
Parameters:
  • name (str) – Name for the new column.

  • expr (pl.Expr) – A Polars expression that evaluates to the column values.

Returns:

A new Result with name appended to data.

Return type:

Result

aggregate(*exprs: polars.Expr, by: str | None = None) Result#

Return a new Result with the data grouped and aggregated.

The by parameter controls the grouping dimension. Not all groupings are valid for every resolution — the matrix below is enforced at call time:

by

static

annual

sub_annual

None

"year"

"month" / "year_month" / "season" / "season_year"

Parameters:
  • *exprs (pl.Expr) – One or more Polars aggregation expressions (e.g. pl.mean("ndvi"), pl.max("rainfall")).

  • by (str | None, optional) – Grouping dimension. None collapses all rows to one. "year" groups by entity + year and is valid for both annual and sub_annual resolution. Other temporal groupings ("month", "year_month", "season", "season_year") require resolution="sub_annual".

Returns:

A new Result whose data is the aggregated frame.

Return type:

Result

Raises:

ValueError – If by is incompatible with resolution, or if by is not a recognised grouping name.

property stats: core_lens.base.namespaces.stats.StatsNamespace#

Return the statistical analysis namespace for this result.

All methods on this namespace return a fresh Result with computed values in data and method parameters in metadata.

Example:

result.stats.describe()
result.stats.correlate(["ndvi", "rainfall"], method="spearman")
result.stats.anomaly("ndvi", mode="cross_sectional", method="zscore")
Returns:

The statistical analysis namespace.

Return type:

StatsNamespace

property plot: core_lens.base.namespaces.plot.PlotNamespace#

Return the visualisation namespace for this result.

Methods here return Lonboard or Plotly objects.

Example:

result.plot.choropleth("ndvi")
result.plot.timeseries(x="year", y="rainfall")
Returns:

The visualisation namespace.

Return type:

PlotNamespace