harmonization
harmonization ¤
DataHarmonizer ¤
DataHarmonizer(
dataframe: DataFrame,
time_column: str = "systime",
uuid_column: str = "uuid",
value_column: str = "value_double",
)
Bases: Base
Data Harmonization for multi-signal timeseries.
Provides utilities to pivot, resample, align, and fill gaps across multiple UUID-keyed signals stored in long (stacked) format.
Methods: - pivot_to_wide: Pivot long-format to wide-format (one column per UUID). - resample_to_uniform: Resample to a uniform time grid with interpolation. - detect_gaps: Identify time gaps per UUID exceeding a threshold. - fill_gaps: Fill detected gaps using various strategies. - align_asof: Align two UUID signals using merge_asof. - merge_multi_signals: End-to-end harmonization pipeline.
Keep a time-sorted copy of dataframe.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataframe
|
DataFrame
|
Long-format input. |
required |
time_column
|
str
|
Timestamp column. Text and pyarrow timestamps are
converted; an empty untyped column becomes |
'systime'
|
uuid_column
|
str
|
Signal identifier column. |
'uuid'
|
value_column
|
str
|
Column holding the values to harmonize. |
'value_double'
|
Raises:
| Type | Description |
|---|---|
ColumnNotFoundError
|
If one of the three columns is missing. |
pivot_to_wide ¤
pivot_to_wide(aggfunc: str = 'first') -> pd.DataFrame
Pivot long-format DataFrame to wide-format with one column per UUID.
Memory: the wide frame is dense, one row per distinct timestamp of
any signal and one column per UUID, so it holds
timestamps x signals cells (8 bytes each for float values)
however sparse the long frame is. Signals sampled at their own
instants barely share rows: 100 such signals of 100,000 samples each
(10 million long rows, about 0.5 GB) pivot to 10 million x 100 cells,
8 GB, mostly NaN. Select the signals you need and resample or round
the timestamps onto a common grid before pivoting large data
(:meth:resample_to_uniform pivots too, then resamples).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aggfunc
|
str
|
Aggregation function for duplicate timestamps ('first', 'mean', 'last'). |
'first'
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with systime as index and one column per UUID. A signal without any value is kept as an all-NaN column. |
resample_to_uniform ¤
resample_to_uniform(
window: str,
method: str = "linear",
fill_limit: int | None = None,
) -> pd.DataFrame
Resample to a uniform time grid with interpolation.
Pivots first, so the full wide frame of :meth:pivot_to_wide (one
row per distinct timestamp, see its memory note) is built before it
is reduced to the grid.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
window
|
str
|
Pandas frequency string (e.g. '1s', '100ms', '1min'). |
required |
method
|
str
|
Interpolation method ('linear', 'time', 'nearest', 'quadratic', 'cubic'). |
'linear'
|
fill_limit
|
int | None
|
Maximum number of consecutive NaNs to fill. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with uniform DatetimeIndex. |
detect_gaps ¤
detect_gaps(threshold: str = '10s') -> pd.DataFrame
Identify time gaps per UUID exceeding the threshold.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
threshold
|
str
|
Minimum gap duration as a pandas Timedelta string. |
'10s'
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with one row per gap: |
fill_gaps ¤
fill_gaps(
strategy: str = "interpolate",
max_gap: str | None = None,
fill_value: float | None = None,
) -> pd.DataFrame
Fill gaps in the wide-format data using the specified strategy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
strategy
|
str
|
One of 'interpolate', 'ffill', 'bfill', 'constant'. |
'interpolate'
|
max_gap
|
str | None
|
Maximum gap size to fill (pandas Timedelta string),
measured from the valid sample before a run of missing values
to the valid sample after it. Larger gaps remain NaN. |
None
|
fill_value
|
float | None
|
Value used when strategy='constant'. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Wide-format DataFrame with gaps filled. |
align_asof ¤
align_asof(
left_uuid: str,
right_uuid: str,
tolerance: str = "1s",
direction: str = "nearest",
) -> pd.DataFrame
Align two UUID signals using merge_asof with configurable tolerance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left_uuid
|
str
|
UUID of the left (reference) signal. |
required |
right_uuid
|
str
|
UUID of the right signal. |
required |
tolerance
|
str
|
Maximum time difference for matching. |
'1s'
|
direction
|
str
|
One of 'nearest', 'backward', 'forward'. |
'nearest'
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with systime, value_left, value_right. |
Warns:
| Type | Description |
|---|---|
DataQualityWarning
|
When a uuid is not in the (non-empty) frame; the result then has no matches for it. |
merge_multi_signals ¤
merge_multi_signals(
uuids: list[str] | None = None,
window: str | None = None,
method: str = "linear",
) -> pd.DataFrame
End-to-end harmonization: pivot, filter, resample, interpolate.
The selected signals are pivoted before resampling: the memory of
:meth:pivot_to_wide applies to them (pass uuids to bound it).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
uuids
|
list[str] | None
|
Optional list of UUIDs to include. None means all. |
None
|
window
|
str | None
|
Optional resample frequency. None means no resampling. |
None
|
method
|
str
|
Interpolation method for resampling. |
'linear'
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Wide-format DataFrame ready for cross-signal analytics. |