Aggregating trajectories¶

No description has been provided for this image

Binder IPYNB HTML

The aggregation approach implemented in TrajectoryCollectionAggregator is based on Andrienko, N., & Andrienko, G. (2011). Spatial generalization and aggregation of massive movement data. IEEE Transactions on visualization and computer graphics, 17(2), 205-219. and consists of the following main steps:

  1. Extracting characteristic points from the trajectories
  2. Grouping the extracted points by spatial proximity
  3. Computing group centroids and corresponding Voronoi cells
  4. Dividing trajectories into segments according to the Voronoi cells
  5. Counting transitions from one cell to another
In [1]:
import pandas as pd
import geopandas as gpd
import movingpandas as mpd
import shapely as shp
import hvplot.pandas
import matplotlib.pyplot as plt
import folium

from geopandas import GeoDataFrame, read_file
from shapely.geometry import Point, LineString, Polygon
from datetime import datetime, timedelta
from holoviews import opts, dim

import warnings

warnings.filterwarnings("ignore")

plot_defaults = {"linewidth": 5, "capstyle": "round", "figsize": (9, 3), "legend": True}
opts.defaults(
    opts.Overlay(active_tools=["wheel_zoom"], frame_width=500, frame_height=400)
)

mpd.show_versions()
MovingPandas 0.20.0

SYSTEM INFO
-----------
python     : 3.10.15 | packaged by conda-forge | (main, Oct 16 2024, 01:15:49) [MSC v.1941 64 bit (AMD64)]
executable : c:\Users\Agarkovam\AppData\Local\miniforge3\envs\mpd-ex\python.exe
machine    : Windows-10-10.0.19045-SP0

GEOS, GDAL, PROJ INFO
---------------------
GEOS       : None
GEOS lib   : None
GDAL       : None
GDAL data dir: None
PROJ       : 9.5.0
PROJ data dir: C:\Users\Agarkovam\AppData\Local\miniforge3\envs\mpd-ex\Library\share\proj

PYTHON DEPENDENCIES
-------------------
geopandas  : 1.0.1
pandas     : 2.2.3
fiona      : None
numpy      : 1.23.1
shapely    : 2.0.6
pyproj     : 3.7.0
matplotlib : 3.9.2
mapclassify: 2.8.1
geopy      : 2.4.1
holoviews  : 1.20.0
hvplot     : 0.11.1
geoviews   : 1.13.0
stonesoup  : 1.4
In [2]:
gdf = read_file("../data/geolife_small.gpkg")
tc = mpd.TrajectoryCollection(gdf, "trajectory_id", t="t")
In [3]:
tc.hvplot(line_width=7.0, tiles="CartoLight")
Out[3]:
In [4]:
tc.explore(column="trajectory_id", cmap="plasma", style_kwds={"weight": 4})
Out[4]:
Make this Notebook Trusted to load map: File -> Trust Notebook

TrajectoryCollectionAggregator¶

Generalizing the trip trajectories significantly speeds up the following aggregation step.

In [5]:
generalized = mpd.MinDistanceGeneralizer(tc).generalize(tolerance=100)
In [6]:
aggregator = mpd.TrajectoryCollectionAggregator(
    generalized,
    max_distance=1000,
    min_distance=100,
    min_stop_duration=timedelta(minutes=5),
)
In [7]:
pts = aggregator.get_significant_points_gdf()
clusters = aggregator.get_clusters_gdf()
(pts.hvplot(geo=True, tiles="CartoLight") * clusters.hvplot(geo=True, color="red"))
Out[7]:
In [8]:
m = pts.explore(marker_kwds={"radius": 3}, name="Significant points")

clusters.explore(m=m, color="red", marker_kwds={"radius": 3}, name="Cluster centroids")

folium.TileLayer("CartoDB positron").add_to(m)
folium.LayerControl().add_to(m)

m
Out[8]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [9]:
flows = aggregator.get_flows_gdf()
In [10]:
(
    flows.hvplot(
        geo=True,
        hover_cols=["weight"],
        line_width=dim("weight") * 7,
        color="#1f77b3",
        tiles="CartoLight",
    )
    * clusters.hvplot(geo=True, color="red", size=dim("n"))
)
Out[10]:
In [11]:
m = flows.explore(
    style_kwds={"weight": 5},
    name="Flows",
)

clusters.explore(
    m=m,
    color="red",
    style_kwds={"style_function": lambda x: {"radius": x["properties"]["n"]}},
    name="Clusters",
)

folium.TileLayer("OpenStreetMap").add_to(m)
folium.LayerControl().add_to(m)

m
Out[11]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [ ]: