{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Splitting trajectories\n", "\n", "\n", "\n", "[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/movingpandas/movingpandas-examples/main?filepath=1-tutorials/6-splitting-trajectories.ipynb)\n", "[![IPYNB](https://img.shields.io/badge/view-ipynb-hotpink)](https://github.com/movingpandas/movingpandas-examples/blob/main/1-tutorials/6-splitting-trajectories.ipynb)\n", "[![HTML](https://img.shields.io/badge/view-html-green)](https://movingpandas.github.io/movingpandas-website/1-tutorials/6-splitting-trajectories.html)\n", "\n", "Gaps are quite common in trajectories. For example, GPS tracks may contain gaps if moving objects enter tunnels where GPS reception is lost. In other use cases, moving objects may leave the observation area for longer time before returning and continuing their recorded track.\n", "\n", "Depending on the use case, we therefore might want to split trajectories at observation gaps that exceed a certain minimum duration:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import geopandas as gpd\n", "import movingpandas as mpd\n", "import shapely as shp\n", "import hvplot.pandas \n", "import matplotlib.pyplot as plt\n", "\n", "from geopandas import GeoDataFrame, read_file\n", "from shapely.geometry import Point, LineString, Polygon\n", "from datetime import datetime, timedelta\n", "from holoviews import opts\n", "\n", "import warnings\n", "warnings.filterwarnings('ignore')\n", "\n", "plot_defaults = {'linewidth':5, 'capstyle':'round', 'figsize':(9,3), 'legend':True}\n", "opts.defaults(opts.Overlay(active_tools=['wheel_zoom'], frame_width=500, frame_height=400))\n", "\n", "mpd.show_versions()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "gdf = read_file('../data/geolife_small.gpkg')\n", "tc = mpd.TrajectoryCollection(gdf, 'trajectory_id', t='t')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "my_traj = tc.trajectories[1]\n", "print(my_traj)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "my_traj.plot(column='speed', vmax=20, **plot_defaults)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## ObservationGapSplitter" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Split the trajectory where then are no observations for at least two minutes:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "split = mpd.ObservationGapSplitter(my_traj).split(gap=timedelta(minutes=2))\n", "split" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "split.to_traj_gdf()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, axes = plt.subplots(nrows=1, ncols=len(split), figsize=(19,4))\n", "for i, traj in enumerate(split):\n", " traj.plot(ax=axes[i], linewidth=5.0, capstyle='round', column='speed', vmax=20)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## StopSplitter" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Split the trajectory where observations stay within 30 meters for at least 1 minute. Discard created trajectories that are shorter than 500 meters long:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "split = mpd.StopSplitter(my_traj).split(max_diameter=30, min_duration=timedelta(minutes=1), min_length=500)\n", "split" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "split.to_traj_gdf()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, axes = plt.subplots(nrows=1, ncols=len(split), figsize=(19,4))\n", "for i, traj in enumerate(split):\n", " traj.plot(ax=axes[i], linewidth=5.0, capstyle='round', column='speed', vmax=20)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## SpeedSplitter" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Split the trajectory where the speed is below one meters per second for at least five minutes:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "split = mpd.SpeedSplitter(my_traj).split(speed=1, duration=timedelta(minutes=5))\n", "split" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "split.to_traj_gdf()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, axes = plt.subplots(nrows=1, ncols=len(split), figsize=(19,4))\n", "for i, traj in enumerate(split):\n", " traj.plot(ax=axes[i], linewidth=5.0, capstyle='round', column='speed', vmax=20)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.10" } }, "nbformat": 4, "nbformat_minor": 4 }