Metric Methods
Define Metric
define_metric(
name: Optional[str] = None,
expression: Optional[str] = None,
aggregation: Optional[Union[str, Callable[[Any], Any]]] = None,
metric_filters: Optional[Dict[str, Any]] = None,
row_condition_expression: Optional[str] = None,
context_state_name: str = 'Default',
ignore_dimensions: Optional[Union[bool, List[str]]] = False,
fillna: Optional[any] = None
)
Defines a metric and stores it in the cube object for later use in queries.
Parameters:
name
: Label for the metric (used in query results)expression
: Calculation formula using [column] references and @custom_functionsaggregation
: How to combine values - pandas aggregation string ('sum', 'mean', 'count') or custom callablemetric_filters
: Filters applied only when evaluating this specific metricrow_condition_expression
: Filter expression applied to rows before calculating the metriccontext_state_name
: Which context state this metric operates inignore_dimensions
: Control how dimensions affect aggregation -True
to ignore all dimensions (grand total), a list of dimension names to ignore specific dimensions, orFalse
(default) for normal dimensional aggregationfillna
: Value to use for replacing Null values on the metric expression and row_condition_expression columns before aggregation. Note: This parameter applies the same value to all columns. For column-specific NA handling, use@pd.fillna()
or@np.nan_to_num()
functions directly in the expression.
Example:
# Define a revenue metric
cube.define_metric(
name='Revenue',
expression='[qty] * [price]',
aggregation='sum'
)
# Sum sales only from Australia
# Note: This differs from using metric_filters={'region': ['Australia']} in how the filtering is applied:
# - row_condition_expression: Fetches all the rows, then applies pandas .query() with backtick syntax
# - metric_filters: Applied at the context state level before metric calculation
# The row_condition_expression fetches all the rows for the column which can result in different aggregation values depending on your data relationships.
cube.define_metric(
name='Australia Sales',
expression='[sales_amount]',
aggregation='sum',
row_condition_expression='[region] == "Australia"'
)
# Define a metric that ignores all dimensions (calculates grand total)
cube.define_metric(
name='Total Revenue',
expression='[qty] * [price]',
aggregation='sum',
ignore_dimensions=True # Ignore all dimensions when aggregating
)
# Define a metric that ignores specific dimensions (partial total)
cube.define_metric(
name='Revenue by Country',
expression='[qty] * [price]',
aggregation='sum',
ignore_dimensions=['city', 'product_category'] # Ignore these dimensions, aggregate only by remaining dimensions
)
# Advanced NA handling - Using the simple fillna parameter (fills all columns with same value)
cube.define_metric(
name='Revenue with NA Handling',
expression='[qty] * [price]',
aggregation='sum',
fillna=0 # Fills both qty and price with 0
)
# Advanced NA handling - Using @functions for column-specific handling
cube.define_metric(
name='Revenue with Column-Specific NA Handling',
expression='@pd.Series([qty]).fillna(1) * @pd.Series([price]).fillna(0)',
aggregation='sum' # Fills [qty] with 1 and [price] with 0
)
Syntax Rules
-
Column References: Columns in metric expressions must be enclosed in square brackets:
[qty]
,[price]
,[cost]
, etc. -
Aggregation Methods: The
aggregation
parameter accepts: -
Pandas group by strings:
'sum'
,'mean'
,'count'
,'min'
,'max'
, etc. -
Custom callable functions:
lambda x: x.quantile(0.95)
or any function that accepts a pandas Series
Define Computed Metric
define_computed_metric(
name: str,
expression: str,
fillna: Optional[Any] = None
) -> None
Defines a post-aggregation computed metric that operates on already aggregated metrics and dimensions.
Parameters:
name
: Unique label for the metric (used in query results)expression
: Calculation formula using [MetricName] references and dimension column referencesfillna
: Optional value to replace NaN computed metrics expression columns before calculation.
Example:
# Define a profit margin percentage computed metric
cube.define_computed_metric(
name='Margin %',
expression='([Revenue] - [Cost]) / [Revenue] * 100',
fillna=0
)
Using in queries:
You must define computed metrics first, then reference them by name in queries:
cube.define_query(
query_name='sales_margin_named',
dimensions={'product'},
metrics=['Revenue', 'Cost'],
computed_metrics=['Margin %'],
)
Register Function
register_function(**kwargs)
Register custom functions to use in metric expressions with @function_name syntax.
Parameters:
**kwargs
: Keyword arguments where each key is the name to use in expressions and each value is the function
Example:
import numpy as np
# Define a custom function
def safe_division(numerator, denominator, default=0.0):
"""Safely divide two arrays, handling division by zero"""
result = numerator / denominator
return result.replace([np.inf, -np.inf], np.nan).fillna(default)
# Register the function with your hypercube
cube.register_function(safe_division=safe_division)
# Use in metric definition
cube.define_metric(
name='Profit Margin %',
expression='@safe_division([revenue] - [cost], [revenue]) * 100',
aggregation='mean'
)