time_accounting
time_accounting ¤
Time and quantity accounting per period (shift, hour, day, ...).
KPIs such as availability, utilization or performance are ratios of durations and quantities within a period. ISO 22400-2 defines them on the time that actually falls inside the period: a stop that starts at 07:00 and lasts until 15:00 contributes 7 h of down time to the 06:00-14:00 shift and 1 h to the 14:00-22:00 shift -- not 8 h to the shift it started in.
Booking a whole interval to the period of its start reading is a common shortcut that breaks every period-level KPI on change-encoded data (one row per transition) and on any interval that crosses a boundary. This module does the accounting correctly:
- :func:
reading_intervals-- one[t_i, t_{i+1})interval per reading, the reading's state held until the next one (over-long gaps can be marked as "no data"). - :func:
shift_periods, :func:grouper_periods, :func:floor_periods-- the period grid covering a time range: shift windows (overnight shifts and the production day included),pd.Grouper/resamplebins, orfloor-aligned windows. Wall-clock bounds are localized in the data's timezone, so a DST day lasts 23 h or 25 h. - :func:
split_intervals-- each interval cut at the period boundaries. - :func:
time_by_period-- seconds per(period, state). - :func:
spread_increments-- a counter increment between two readings spread over(t_prev, t]in proportion to time, so the parts produced across a boundary are shared between the periods they were produced in.
reading_intervals ¤
reading_intervals(
times: Series, states: Series, *, max_gap: Any = None
) -> pd.DataFrame
One interval per reading: its state held until the next reading.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
times
|
Series
|
Reading times of one signal, sorted. |
required |
states
|
Series
|
State per reading, aligned with |
required |
max_gap
|
Any
|
Optional cap ( |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with |
DataFrame
|
successor and opens no interval. |
shift_periods ¤
shift_periods(
t0: Timestamp,
t1: Timestamp,
shift_definitions: Mapping[str, tuple[str, str]],
*,
production_day: bool = True
) -> pd.DataFrame
Shift windows covering [t0, t1], labeled like the readings would be.
Each window is labeled with the shift that
:func:~ts_shape.utils.shifts.assign_shift gives a reading in it
("unknown" for time no shift covers) and the date that
:func:~ts_shape.utils.shifts.production_dates gives it
(production_day=True: an overnight shift is one window on its start
date) or the calendar date (production_day=False: an overnight shift
is cut at midnight into two windows). Wall-clock bounds are localized in
the timezone of t0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
t0
|
Timestamp
|
Start of the range. |
required |
t1
|
Timestamp
|
End of the range. |
required |
shift_definitions
|
Mapping[str, tuple[str, str]]
|
|
required |
production_day
|
bool
|
Label by production day (default) or calendar date. |
True
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with |
DataFrame
|
sorted windows overlapping |
grouper_periods ¤
grouper_periods(
t0: Timestamp, t1: Timestamp, window: Any
) -> pd.DataFrame
The pd.Grouper(freq=window) bins covering [t0, t1].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
t0
|
Timestamp
|
Start of the range. |
required |
t1
|
Timestamp
|
End of the range. |
required |
window
|
Any
|
Resample frequency ( |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with |
DataFrame
|
(the true bin bounds, calendar-correct on DST days and for |
DataFrame
|
right-labeled frequencies), sorted. |
floor_periods ¤
floor_periods(
t0: Timestamp, t1: Timestamp, window: Any
) -> pd.DataFrame
Windows labeled by floor_local(t, window) covering [t0, t1].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
t0
|
Timestamp
|
Start of the range. |
required |
t1
|
Timestamp
|
End of the range. |
required |
window
|
Any
|
Fixed frequency ( |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with |
DataFrame
|
and |
DataFrame
|
later, a calendar day for |
split_intervals ¤
split_intervals(
intervals: DataFrame,
periods: DataFrame,
*,
keys: Sequence[str]
) -> pd.DataFrame
Cut each interval at the period boundaries.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
intervals
|
DataFrame
|
|
required |
periods
|
DataFrame
|
Non-overlapping periods with |
required |
keys
|
Sequence[str]
|
Period label columns copied to each piece. |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per (interval, period) with positive overlap: the |
DataFrame
|
the interval's other columns, |
DataFrame
|
|
time_by_period ¤
time_by_period(
intervals: DataFrame,
periods: DataFrame,
*,
keys: Sequence[str],
states: Sequence[str]
) -> pd.DataFrame
Seconds per period and state, intervals split at period boundaries.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
intervals
|
DataFrame
|
|
required |
periods
|
DataFrame
|
Non-overlapping periods with |
required |
keys
|
Sequence[str]
|
Period label columns. |
required |
states
|
Sequence[str]
|
The state labels to report; each becomes a float column of seconds (0 when a period holds none of it). Intervals in other states are ignored. |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per period that overlaps any interval, in time order, with |
DataFrame
|
the |
spread_increments ¤
spread_increments(
times: Series,
increments: Series,
periods: DataFrame,
*,
keys: Sequence[str]
) -> pd.DataFrame
Counter increments spread over the time they were produced in.
The increment reported at reading t_i was produced during
(t_{i-1}, t_i]. It is shared between the periods that interval
overlaps, in proportion to the time in each (constant production rate
between two readings). An increment with no preceding reading, or one
between two readings at the same time, goes to the period holding its
reading.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
times
|
Series
|
Reading times, sorted. |
required |
increments
|
Series
|
Increment per reading (aligned with |
required |
periods
|
DataFrame
|
Non-overlapping periods with |
required |
keys
|
Sequence[str]
|
Period label columns. |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with the |
DataFrame
|
period that received any share (zero shares included). |
counter_by_period ¤
counter_by_period(
times: Series,
values: Series,
periods: DataFrame,
reading_keys: DataFrame,
*,
keys: Sequence[str]
) -> pd.DataFrame
Reset-aware counter quantity and resets per period.
The reset-aware increments (:func:~ts_shape.utils.counters.counter_increments)
are spread over the time they were produced in
(:func:spread_increments); a reset is a point event and counts in the
period of the reading that shows it. Missing readings are skipped.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
times
|
Series
|
Reading times of one counter, sorted. |
required |
values
|
Series
|
Counter readings, aligned with |
required |
periods
|
DataFrame
|
Non-overlapping periods with |
required |
reading_keys
|
DataFrame
|
The |
required |
keys
|
Sequence[str]
|
Period label columns. |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with the |
DataFrame
|
(int), one row per period that holds a reading or received a share, |
DataFrame
|
sorted by the |