Trajectory
| API | Description | Example |
|---|---|---|
interpolate |
Fill gaps in a trajectory by inserting interpolated points. | Fill recording gaps |
interpolate_at |
Query each user's interpolated position at one or more timestamps. | Ask for a position at a given time |
trajectory_distance |
Compute a similarity/distance metric between two trajectories. | Compare two trajectories |
smooth |
Smooth a trajectory's positions using a named algorithm. | Smooth GPS noise |
cluster_trajectory_shapes |
Cluster a list of independent trajectories by their overall shape. | Group trajectories by shape |
cluster_trajectory_shapes_from_segments |
Cluster trajectory shapes directly from a segment()-output (or Triplegs.points) frame, splitting into per-segment trajectories internally. |
Group trajectories by shape |
interpolate(traj, method='linear', sampling_rate_s=3600.0, *, datetime_col=None, lat_col=None, lng_col=None, uid_col=None, **method_kwargs)
Fill gaps in a trajectory by inserting interpolated points.
For every gap between two chronologically consecutive points of the same
user whose time delta exceeds sampling_rate_s, exactly one new point
is inserted at t[i-1] + sampling_rate_s (matching PTRAIL's
Interpolation.interpolate_position insertion policy: a large gap is
not filled iteratively down to sampling_rate_s-sized steps -- only
one point is added per gap, regardless of how large it is).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj
|
Any
|
Trajectory dataframe; any Narwhals-compatible eager backend. |
required |
method
|
str
|
Name of the interpolation algorithm to run. One of |
'linear'
|
sampling_rate_s
|
float
|
Maximum time gap, in seconds, allowed between consecutive points
before an interpolated point is inserted. Default |
3600.0
|
datetime_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
lat_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
lng_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
uid_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
**method_kwargs
|
Any
|
Method-specific parameters, forwarded to the matching
|
{}
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
The expanded trajectory (original points, plus any inserted points) in the same backend as input, sorted chronologically per user. |
Examples:
>>> import pandas as pd
>>> import fastmob
>>> df = pd.DataFrame({
... "uid": [1, 1, 1],
... "lat": [0.0, 1.0, 2.0],
... "lng": [0.0, 0.0, 0.0],
... "datetime": pd.to_datetime(
... ["2020-01-01 00:00", "2020-01-01 02:00", "2020-01-01 03:00"]
... ),
... })
>>> from fastmob.trajectory import interpolate
>>> out = interpolate(df, method="linear", sampling_rate_s=3600.0)
>>> len(out) >= len(df)
True
References
- [PTRAIL] Haranwala, Y.J., & Haidri, S. PTRAIL: A Python package for parallel trajectory data preprocessing.
- [Nogueira2016] Nogueira, T.O. "kinematic_interpolation.py" (2016).
Worked example: Fill recording gaps
interpolate_at(traj, at, method='linear', *, datetime_col=None, lat_col=None, lng_col=None, uid_col=None)
Query each user's interpolated position at one or more timestamps.
Unlike fastmob.trajectory.interpolate, this never changes a
user's own point count -- it answers "where was this user at time t?"
independently per user and per query timestamp. A query time outside a
user's own [min(datetime), max(datetime)] range is marked invalid
(valid=False, NaN position) rather than raising, matching this
codebase's validity-mask convention over exceptions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj
|
Any
|
Trajectory dataframe; any Narwhals-compatible eager backend. |
required |
at
|
Any
|
A single timestamp-like, or a sequence of timestamp-likes. Every
user is queried at every timestamp in |
required |
method
|
str
|
|
'linear'
|
datetime_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
lat_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
lng_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
uid_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per |
Examples:
>>> import pandas as pd
>>> import fastmob
>>> df = pd.DataFrame({
... "uid": [1, 1, 1],
... "lat": [0.0, 1.0, 2.0],
... "lng": [0.0, 0.0, 0.0],
... "datetime": pd.to_datetime(
... ["2020-01-01 00:00", "2020-01-01 01:00", "2020-01-01 02:00"]
... ),
... })
>>> from fastmob.trajectory import interpolate_at
>>> out = interpolate_at(df, at="2020-01-01 00:30", method="linear")
>>> bool(out["valid"].iloc[0])
True
Worked example: Ask for a position at a given time
trajectory_distance(traj_a, traj_b, method='dtw', *, datetime_col_a=None, lat_col_a=None, lng_col_a=None, uid_col_a=None, datetime_col_b=None, lat_col_b=None, lng_col_b=None, uid_col_b=None, **method_kwargs)
Compute a similarity/distance metric between two trajectories.
Compares exactly two whole point-sequences -- each side must be a single user's trajectory (or have no user column at all), not a multi-user dataframe. Point-to-point distances are computed via haversine, matching every other fastmob measure's geographic-distance convention.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj_a
|
Any
|
Trajectory dataframes; any Narwhals-compatible eager backend, or a
|
required |
traj_b
|
Any
|
Trajectory dataframes; any Narwhals-compatible eager backend, or a
|
required |
method
|
str
|
|
'dtw'
|
datetime_col_a
|
str | None
|
Explicit column overrides for |
None
|
lat_col_a
|
str | None
|
Explicit column overrides for |
None
|
lng_col_a
|
str | None
|
Explicit column overrides for |
None
|
uid_col_a
|
str | None
|
Explicit column overrides for |
None
|
datetime_col_b
|
str | None
|
Explicit column overrides for |
None
|
lat_col_b
|
str | None
|
Explicit column overrides for |
None
|
lng_col_b
|
str | None
|
Explicit column overrides for |
None
|
uid_col_b
|
str | None
|
Explicit column overrides for |
None
|
**method_kwargs
|
Any
|
Method-specific parameters, forwarded to the matching
|
{}
|
Returns:
| Type | Description |
|---|---|
float
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If either side's user-ID column contains more than one distinct user. |
Examples:
>>> import pandas as pd
>>> import fastmob
>>> traj_a = pd.DataFrame({
... "lat": [0.0, 1.0, 2.0], "lng": [0.0, 0.0, 0.0],
... "datetime": pd.date_range("2020-01-01", periods=3, freq="h"),
... })
>>> traj_b = pd.DataFrame({
... "lat": [0.0, 1.0, 2.0], "lng": [0.1, 0.1, 0.1],
... "datetime": pd.date_range("2020-01-01", periods=3, freq="h"),
... })
>>> from fastmob.trajectory import trajectory_distance
>>> trajectory_distance(traj_a, traj_b, method="dtw") > 0
True
References
- [Vlachos2002] Vlachos, M., Kollios, G., & Gunopulos, D. (2002). Discovering similar multidimensional trajectories. ICDE 2002.
Worked example: Compare two trajectories
smooth(traj, method='kalman_cv', *, datetime_col=None, lat_col=None, lng_col=None, uid_col=None, **method_kwargs)
Smooth a trajectory's positions using a named algorithm.
Every row's (lat, lng) is replaced with a denoised estimate at its
original timestamp; row count and row order are unchanged (unlike
fastmob.trajectory.interpolate, which inserts new points).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj
|
Any
|
Trajectory dataframe; any Narwhals-compatible eager backend. |
required |
method
|
str
|
Name of the smoothing algorithm to run. Only |
'kalman_cv'
|
datetime_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
lat_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
lng_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
uid_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
**method_kwargs
|
Any
|
Method-specific parameters, forwarded to the matching
|
{}
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
The trajectory with smoothed |
Examples:
>>> import pandas as pd
>>> import fastmob
>>> df = pd.DataFrame({
... "uid": [1, 1, 1],
... "lat": [0.0, 1.0, 2.0],
... "lng": [0.0, 0.0, 0.0],
... "datetime": pd.date_range("2020-01-01", periods=3, freq="h"),
... })
>>> from fastmob.trajectory import smooth
>>> out = smooth(df, method="kalman_cv")
>>> len(out) == len(df)
True
References
- [GJH2020] Graser, A., Jankowski, P., & Heistermann, M. (2020).
MovingPandas
KalmanSmootherCV. https://github.com/movingpandas/movingpandas
Worked example: Smooth GPS noise
cluster_trajectory_shapes(trajectories, depth=4, epsilon=0.05, min_cluster_size=2, *, lat_col=None, lng_col=None, datetime_col=None)
Cluster a list of independent trajectories by their overall shape.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trajectories
|
Sequence
|
Each element is a single trajectory: any Narwhals-compatible eager
dataframe (or |
required |
depth
|
int
|
Number of distance-geometry levels (signature length is
|
4
|
epsilon
|
float
|
DBSCAN neighborhood radius over the normalized signature space
(values are in |
0.05
|
min_cluster_size
|
int
|
DBSCAN minimum points per cluster; must be |
2
|
lat_col
|
str
|
Explicit column name overrides; auto-detected per trajectory when None. |
None
|
lng_col
|
str
|
Explicit column name overrides; auto-detected per trajectory when None. |
None
|
datetime_col
|
str
|
Explicit column name overrides; auto-detected per trajectory when None. |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
One cluster label per input trajectory, in input order. |
Examples:
>>> import pandas as pd
>>> import fastmob
>>> from fastmob.trajectory import cluster_trajectory_shapes
>>> line_a = pd.DataFrame({
... "lat": [0.0, 1.0, 2.0], "lng": [0.0, 0.0, 0.0],
... "datetime": pd.date_range("2020-01-01", periods=3, freq="h"),
... })
>>> line_b = pd.DataFrame({
... "lat": [10.0, 11.0, 12.0], "lng": [10.0, 10.0, 10.0],
... "datetime": pd.date_range("2020-01-01", periods=3, freq="h"),
... })
>>> labels = cluster_trajectory_shapes([line_a, line_b], depth=2, epsilon=0.1)
>>> labels[0] == labels[1]
np.True_
Worked example: Group trajectories by shape
cluster_trajectory_shapes_from_segments(traj, segment_col='segment_id', uid_col=None, depth=4, epsilon=0.05, min_cluster_size=2, *, lat_col=None, lng_col=None, datetime_col=None)
Cluster trajectory shapes directly from a segment()-output (or
Triplegs.points) frame, splitting into per-segment trajectories internally.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj
|
dataframe
|
A dataframe already carrying a segment/group id column (e.g. the
output of |
required |
segment_col
|
str
|
Column identifying which rows belong to the same trajectory.
Default |
'segment_id'
|
uid_col
|
str
|
When given, groups by |
None
|
**kwargs
|
Forwarded to |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
The distinct |
Worked example: Group trajectories by shape