Movingpandas
IO
Create trajectory
from datetime import datetime
import geopandas as gpd
import movingpandas as mpd
import pandas as pd
from shapely.geometry import Point
df = pd.DataFrame(
{
"t": pd.date_range("2022-01-01", periods=3),
"geometry": [Point(0, 0), Point(0, 1), Point(0, 2)],
}
).set_index("t")
gdf = gpd.GeoDataFrame(df, crs=31256)
# backtrack
df = pd.DataFrame(
{
"t": pd.date_range("2022-01-01", periods=4),
"geometry": [Point(0, 0), Point(0, 2), Point(0, 1), Point(0, 4)],
}
).set_index("t")
gdf = gpd.GeoDataFrame(df, crs=31256)
# speed of ~13 m/s
df = pd.DataFrame(
{"lat": np.linspace(0, 0.1, num=5), "lon": np.linspace(0, 0.1, num=5)},
index=pd.date_range("01-01-2020", periods=5, freq="5min", tz="UTC"),
)
# con
df = pd.DataFrame(
{"lat": [0, 0.01, 0.03, 0.06, 0.1], "lon": [0, 0.01, 0.03, 0.06, 0.1]},
index=pd.date_range("01-01-2020", periods=5, freq="5min", tz="UTC"),
)
df = pd.DataFrame(
data={
"time": pd.date_range("2000", freq="D", periods=3),
"lon": [1, 2, 3],
"lat": [1, 2, 3],
}
).set_index("time")
gdf = gpd.GeoDataFrame(
df.copy(),
geometry=gpd.points_from_xy(df["lon"], df["lat"]),
crs="epsg:4326",
)
gdf = gpd.GeoDataFrame(df, crs="epsg:4326")
traj = mpd.Trajectory(gdf, 1)
traj
traj.df
Create trajectory collection
df = pd.DataFrame(
{
"t": pd.date_range("2020-01-01", periods=5, freq="min"),
"trajectory_id": [1, 1, 2, 2, 2],
"geometry": [Point(0, 0), Point(0, 1), Point(0, 2), Point(0, 3), Point(0, 4)],
}
)
gdf = gpd.GeoDataFrame(df, crs=31256)
trajc = mpd.TrajectoryCollection(gdf, traj_id_col="trajectory_id", t="t")
trajc = mpd.TrajectoryCollection(df, traj_id_col="COL", min_length=100) # min_length in meters
to linestring
traj.to_traj_gdf()
to points
traj.to_point_gdf()
Analytics
See trajectories
trajc.trajectories[0]
for traj in trajc:
print(traj)
Speed
traj.add_speed()
Distance
traj.add_distance()
Timedelta
traj.add_timedelta()
Direction
traj.add_direction()
Angular difference
traj.add_angular_difference()
Length
length = traj.get_length()
import pint
ureg = pint.UnitRegistry()
length_m = length * ureg.m
length_nm = length_m.to("nautical_mile")
Interpolate at a timestamp
from datetime import datetime, timezone
pt = traj.get_position_at(datetime(2022, 1, 1, 0, 15, tzinfo=timezone.utc))
pts = {}
for dt in pd.date_range(
start=pd.Timedelta.ceil(gdf.index.min(), freq="15min"),
end=pd.Timedelta.floor(gdf.index.max(), freq="15min"),
freq="15min",
):
pts[dt] = traj.get_position_at(dt)
Split trajectory
Split trajectory based on time
trajc = mpd.TemporalSplitter(traj).split(mode="day")
Split trajectory based on speed
from datetime import timedelta
trajc = mpd.SpeedSplitter(traj).split(speed=0, duration=timedelta(minutes=30), min_length=1000)
Split trajectory based on stops
trajc = mpd.StopSplitter(traj).split(min_duration=timedelta(minutes=30), max_diameter=30, min_length=500)
Split based on missing data
mpd.ObservationGapSplitter(traj_collection).split(gap=timedelta(minutes=5))
Filter trajectories/points
trajc.trajectories[0]
Keep trajectories longer than a certain duration
min_duration = timedelta(days=5)
trajc2 = trajc.copy()
trajc2.trajectories = [traj for traj in trajc if traj.get_duration() > min_duration]
trajc2
Drop spurious points based on speed
traj.add_speed()
gdf = traj.to_point_gdf()
gdf = gdf[gdf["speed"] < 41.1556].reset_index(drop=True) # 80 knots
Interpolate trajectories
traj_i = mpd.DouglasPeuckerGeneralizer(traj).generalize(tolerance=0.001)
traj_i = mpd.MinTimeDeltaGeneralizer(traj).generalize(tolerance=timedelta(minutes=15))
Plotting
tjaj.plot()
hv_kwargs = dict(hover_cols=["report_date", "latitude", "longitude"], frame_height=300, frame_width=300)
traj.hvplot(**hv_kwargs)