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)