floodlight.metrics.zone_aggregation
- floodlight.metrics.zone_aggregation.aggregate_property_by_zones(property_to_aggregate, binning_property, zones, zone_names=None, aggregation='sum')[source]
Aggregates a property over threshold-based zones of another property.
This function bins frames based on the value of
binning_propertyand aggregates values fromproperty_to_aggregatewithin each zone. Common use cases include calculating distance covered per velocity zone or time spent in different intensity zones [1].- Parameters:
property_to_aggregate (PlayerProperty or TeamProperty) – Property values to aggregate. For PlayerProperty, shape is (T, N) where T is the number of frames and N is the number of players. For TeamProperty, shape is (T,) where T is the number of frames.
binning_property (PlayerProperty or TeamProperty) – Property values used to determine zone membership. Must have the same shape as
property_to_aggregate.zones (list[tuple[Numeric, Numeric]]) – List of (min, max) threshold tuples defining each zone. Zones use half-open intervals [min, max) where the minimum is inclusive and maximum is exclusive. For example, [(0, 2), (2, 4)] creates two zones: [0, 2) and [2, 4).
zone_names (list[str], optional) – Names for each zone. If None, zones are named as “min to max”. Must have the same length as
zonesif provided.aggregation (str, optional) – Aggregation function to apply within each zone. Options:
“sum”: Sum of property values in zone
“count”: Number of frames with valid data in zone
“mean”: Average property value in zone
“min”: Minimum property value in zone
“max”: Maximum property value in zone
Default is ‘sum’.
- Returns:
zone_aggregates – DataFrame with aggregated values. For PlayerProperty inputs, rows correspond to players and columns to zones. For TeamProperty inputs, a single-row DataFrame is returned. Empty zones (no frames matching) return NaN for mean/min/max and 0 for sum/count.
- Return type:
pd.DataFrame
Notes
Valid property combinations:
PlayerProperty by PlayerProperty: Both must have shape (T, N) with matching T and N
TeamProperty by TeamProperty: Both must have shape (T,) with matching T
PlayerProperty by TeamProperty: Aggregation property has shape (T, N), binning property has shape (T,). The binning values are broadcast across all players.
Invalid combination:
TeamProperty by PlayerProperty: Cannot bin a single team value using player-specific thresholds.
Frames where either property has NaN values are excluded from all aggregations. The boundary handling uses half-open intervals [min, max) to avoid ambiguity at zone boundaries.
Examples
Calculate distance covered in velocity zones for each player:
>>> import numpy as np >>> from floodlight import PlayerProperty >>> from floodlight.metrics.zone_aggregation import aggregate_property_by_zones
>>> # Create sample data: 4 frames, 2 players >>> distances = PlayerProperty( ... property=np.array([[10, 5], [10, 5], [10, 5], [10, 5]], dtype=float), ... name="distance" ... ) >>> velocities = PlayerProperty( ... property=np.array([[1, 6], [3, 8], [1, 6], [3, 8]], dtype=float), ... name="velocity" ... ) >>> # Define velocity zones (m/s) >>> zones = [(0, 2), (2, 4), (5, 9)] >>> zone_names = ["Low", "Medium", "High"] >>> result = aggregate_property_by_zones( ... distances, velocities, zones, zone_names, aggregation='sum' ... ) >>> result Low Medium High 0 20.0 20.0 0.0 1 0.0 0.0 20.0
Calculate time spent (frame count) in metabolic power zones:
>>> power = PlayerProperty( ... property=np.array([[5, 15], [8, 25], [12, 30], [6, 18]], dtype=float), ... name="power" ... ) >>> zones = [(0, 10), (10, 20), (20, 35)] >>> result = aggregate_property_by_zones( ... power, power, zones, aggregation='count' ... ) >>> result 0 to 10 10 to 20 20 to 35 0 3.0 1.0 0.0 1 0.0 2.0 2.0
References