Vega-Altair: A declarative statistical visualization library for Python.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Expression system for calculated fields, conditional logic, and dynamic values using Vega expression language with mathematical, string, and logical operations. Expressions enable sophisticated data transformations and conditional visualizations.
Comprehensive expression interface providing access to mathematical, string, logical, and utility functions from the Vega expression language.
class ExpressionAPI:
"""Main expression interface with extensive function library."""
# Constants
NaN: float
PI: float
E: float
LN2: float
LN10: float
LOG2E: float
LOG10E: float
SQRT1_2: float
SQRT2: float
# Mathematical functions
def abs(self, value):
"""Absolute value."""
def acos(self, value):
"""Arccosine in radians."""
def asin(self, value):
"""Arcsine in radians."""
def atan(self, value):
"""Arctangent in radians."""
def atan2(self, y, x):
"""Two-argument arctangent."""
def ceil(self, value):
"""Ceiling (round up to integer)."""
def clamp(self, value, min_val, max_val):
"""Clamp value to range [min, max]."""
def cos(self, value):
"""Cosine."""
def exp(self, value):
"""Exponential function (e^x)."""
def floor(self, value):
"""Floor (round down to integer)."""
def log(self, value):
"""Natural logarithm."""
def max(self, *values):
"""Maximum of values."""
def min(self, *values):
"""Minimum of values."""
def pow(self, base, exponent):
"""Power function (base^exponent)."""
def random(self):
"""Random number [0, 1)."""
def round(self, value):
"""Round to nearest integer."""
def sin(self, value):
"""Sine."""
def sqrt(self, value):
"""Square root."""
def tan(self, value):
"""Tangent."""
# String functions
def indexof(self, string, substring):
"""Index of substring in string."""
def join(self, array, separator=None):
"""Join array elements into string."""
def lastindexof(self, string, substring):
"""Last index of substring in string."""
def length(self, string_or_array):
"""Length of string or array."""
def lower(self, string):
"""Convert to lowercase."""
def pad(self, string, length, character=None, align=None):
"""Pad string to specified length."""
def regexp(self, string, pattern, flags=None):
"""Test string against regular expression."""
def replace(self, string, pattern, replacement):
"""Replace substring or pattern."""
def slice(self, string_or_array, start, end=None):
"""Extract substring or subarray."""
def split(self, string, separator, limit=None):
"""Split string into array."""
def substring(self, string, start, end=None):
"""Extract substring."""
def trim(self, string):
"""Remove leading/trailing whitespace."""
def truncate(self, string, length, align=None, ellipsis=None):
"""Truncate string to specified length."""
def upper(self, string):
"""Convert to uppercase."""
# Array functions
def extent(self, array):
"""Min and max values of array."""
def indexof_array(self, array, value):
"""Index of value in array."""
def lastindexof_array(self, array, value):
"""Last index of value in array."""
def peek(self, array):
"""Last element of array."""
def reverse(self, array):
"""Reverse array."""
def sort(self, array):
"""Sort array."""
# Date/time functions
def now(self):
"""Current timestamp."""
def datetime(self, year, month=None, day=None, hour=None, minute=None, second=None, millisecond=None):
"""Create date from components."""
def date(self, datetime):
"""Extract date part."""
def day(self, datetime):
"""Day of month (1-31)."""
def dayofyear(self, datetime):
"""Day of year (1-366)."""
def year(self, datetime):
"""Year."""
def quarter(self, datetime):
"""Quarter (0-3)."""
def month(self, datetime):
"""Month (0-11)."""
def hours(self, datetime):
"""Hours (0-23)."""
def minutes(self, datetime):
"""Minutes (0-59)."""
def seconds(self, datetime):
"""Seconds (0-59)."""
def milliseconds(self, datetime):
"""Milliseconds (0-999)."""
def time(self, datetime):
"""Time in milliseconds since epoch."""
def timezoneoffset(self, datetime):
"""Timezone offset in minutes."""
def utc(self, year, month=None, day=None, hour=None, minute=None, second=None, millisecond=None):
"""Create UTC date."""
# Logical functions
def if_(self, test, then, else_=None):
"""Conditional expression."""
def isArray(self, value):
"""Test if value is array."""
def isBoolean(self, value):
"""Test if value is boolean."""
def isDate(self, value):
"""Test if value is date."""
def isDefined(self, value):
"""Test if value is defined."""
def isFinite(self, value):
"""Test if value is finite number."""
def isNaN(self, value):
"""Test if value is NaN."""
def isNumber(self, value):
"""Test if value is number."""
def isObject(self, value):
"""Test if value is object."""
def isRegExp(self, value):
"""Test if value is regular expression."""
def isString(self, value):
"""Test if value is string."""
def isValid(self, value):
"""Test if value is valid (not null, undefined, or NaN)."""
def inrange(self, value, min_val, max_val):
"""Test if value is in range [min, max]."""
# Format functions
def format(self, value, specifier):
"""Format number with d3-format specifier."""
def timeFormat(self, datetime, specifier):
"""Format date with d3-time-format specifier."""
def timeParse(self, string, specifier):
"""Parse date string with d3-time-format specifier."""
def utcFormat(self, datetime, specifier):
"""Format UTC date."""
def utcParse(self, string, specifier):
"""Parse UTC date string."""
# Type conversion functions
def toBoolean(self, value):
"""Convert to boolean."""
def toDate(self, value):
"""Convert to date."""
def toNumber(self, value):
"""Convert to number."""
def toString(self, value):
"""Convert to string."""
# Statistical functions
def sampleNormal(self, mu=None, sigma=None):
"""Sample from normal distribution."""
def cumulativeNormal(self, value, mu=None, sigma=None):
"""Cumulative normal distribution."""
def densityNormal(self, value, mu=None, sigma=None):
"""Normal probability density."""
def quantileNormal(self, p, mu=None, sigma=None):
"""Normal quantile function."""
def sampleLogNormal(self, mu=None, sigma=None):
"""Sample from log-normal distribution."""
def cumulativeLogNormal(self, value, mu=None, sigma=None):
"""Cumulative log-normal distribution."""
def densityLogNormal(self, value, mu=None, sigma=None):
"""Log-normal probability density."""
def quantileLogNormal(self, p, mu=None, sigma=None):
"""Log-normal quantile function."""
def sampleUniform(self, min_val=None, max_val=None):
"""Sample from uniform distribution."""
def cumulativeUniform(self, value, min_val=None, max_val=None):
"""Cumulative uniform distribution."""
def densityUniform(self, value, min_val=None, max_val=None):
"""Uniform probability density."""
def quantileUniform(self, p, min_val=None, max_val=None):
"""Uniform quantile function."""
# Color functions
def rgb(self, r, g, b):
"""Create RGB color."""
def hsl(self, h, s, l):
"""Create HSL color."""
def lab(self, l, a, b):
"""Create Lab color."""
def hcl(self, h, c, l):
"""Create HCL color."""
def luminance(self, color):
"""Calculate color luminance."""
def contrast(self, color1, color2):
"""Calculate color contrast ratio."""
# Geographic functions
def geoArea(self, feature):
"""Geographic area of feature."""
def geoBounds(self, feature):
"""Geographic bounds of feature."""
def geoCentroid(self, feature):
"""Geographic centroid of feature."""
def geoContains(self, feature, point):
"""Test if feature contains point."""
# Global expression instance
expr = ExpressionAPI()Object for referencing fields in the current data record within expressions.
class DatumExpression:
"""Reference to current data record fields."""
def __getattr__(self, field_name):
"""Access field by name: datum.fieldname"""
def __getitem__(self, field_name):
"""Access field by key: datum['field name']"""
# Global datum instance
datum = DatumExpression()Functions for creating conditional logic and branching expressions.
def condition(predicate, if_true, if_false=None):
"""
Create conditional encoding.
Parameters:
- predicate: Test condition (parameter, selection, or expression)
- if_true: Value/encoding when condition is true
- if_false: Value/encoding when condition is false
Returns:
dict: Conditional specification
"""
def when(predicate):
"""
Start conditional chain.
Parameters:
- predicate: Test condition
Returns:
ChainedWhen: Object for method chaining
"""
class ChainedWhen:
def then(self, value):
"""Value when condition is true."""
class Then:
def when(self, predicate):
"""Additional condition."""
def otherwise(self, value):
"""Final fallback value."""import altair as alt
# Basic mathematical operations
chart = alt.Chart(data).mark_circle().encode(
x='x:Q',
y='y:Q',
size=alt.expr('sqrt(datum.value) * 10')
)
# Complex calculations
chart = alt.Chart(data).mark_point().encode(
x='x:Q',
y='y:Q'
).transform_calculate(
distance=alt.expr('sqrt(pow(datum.x - 50, 2) + pow(datum.y - 50, 2))'),
angle=alt.expr('atan2(datum.y - 50, datum.x - 50) * 180 / PI')
)# String processing
chart = alt.Chart(data).mark_text().encode(
x='x:Q',
y='y:Q',
text=alt.expr('upper(slice(datum.name, 0, 3))')
).transform_calculate(
short_name=alt.expr('length(datum.name) > 10 ? truncate(datum.name, 10) : datum.name'),
initials=alt.expr('split(datum.name, " ")[0][0] + split(datum.name, " ")[1][0]')
)# Date calculations
chart = alt.Chart(data).mark_line().encode(
x='date:T',
y='value:Q'
).transform_calculate(
year=alt.expr('year(datum.date)'),
quarter=alt.expr('quarter(datum.date)'),
day_of_year=alt.expr('dayofyear(datum.date)'),
is_weekend=alt.expr('day(datum.date) == 0 || day(datum.date) == 6')
)# Simple conditional
chart = alt.Chart(data).mark_circle().encode(
x='x:Q',
y='y:Q',
color=alt.expr('datum.value > 50 ? "red" : "blue"')
)
# Complex conditional chain
chart = alt.Chart(data).mark_circle().encode(
x='x:Q',
y='y:Q',
color=alt.when(
alt.datum.value > 80
).then(
alt.value('red')
).when(
alt.datum.value > 60
).then(
alt.value('orange')
).when(
alt.datum.value > 40
).then(
alt.value('yellow')
).otherwise(
alt.value('blue')
)
)# Statistical calculations
chart = alt.Chart(data).mark_circle().encode(
x='x:Q',
y='y:Q',
size=alt.expr('densityNormal(datum.value, 50, 15) * 1000')
).transform_calculate(
z_score=alt.expr('(datum.value - 50) / 15'),
percentile=alt.expr('cumulativeNormal(datum.value, 50, 15)')
)# Color calculations
chart = alt.Chart(data).mark_circle().encode(
x='x:Q',
y='y:Q',
color=alt.expr('hsl(datum.value * 360 / 100, 0.7, 0.5)'),
stroke=alt.expr('contrast("white", hsl(datum.value * 360 / 100, 0.7, 0.5)) > 4.5 ? "black" : "white"')
)# Data validation expressions
chart = alt.Chart(data).mark_circle().encode(
x='x:Q',
y='y:Q',
opacity=alt.expr('isValid(datum.value) && isFinite(datum.value) ? 1.0 : 0.3')
).transform_filter(
alt.expr('isDefined(datum.x) && isDefined(datum.y)')
)# Using parameters in expressions
threshold = alt.param(value=50)
multiplier = alt.param(value=2)
chart = alt.Chart(data).add_params(
threshold, multiplier
).mark_circle().encode(
x='x:Q',
y='y:Q',
size=alt.expr(f'max(10, min(500, datum.value * {multiplier}))'),
color=alt.expr(f'datum.value > {threshold} ? "red" : "blue"')
)from typing import Union, Any, Dict
# Expression types
ExpressionString = str
ExpressionRef = Dict[str, Any]
Expression = Union[ExpressionString, ExpressionRef]
# Conditional types
ConditionalPredicate = Union[str, Dict[str, Any]]
ConditionalValue = Union[Any, Dict[str, Any]]
# Datum field reference
DatumRef = Union[str, Dict[str, Any]]
# Function result types
BooleanExpression = Expression
NumberExpression = Expression
StringExpression = Expression
DateExpression = Expression
ColorExpression = Expression
ArrayExpression = ExpressionInstall with Tessl CLI
npx tessl i tessl/pypi-altair