{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Stop Detection\n", "\n", "\n", "\n", "There are no definitive answers when it comes to detecting / extracting stops from movement trajectories. Due to tracking inaccuracies, movement speed rarely goes to true zero. GPS tracks, for example, tend to keep moving around the object's stop location. \n", "\n", "Suitable stop definitions are also highly application dependent. For example, an application may be interested in analyzing trip purposes. To do so, analysts would be interested in stops that are longer than, for example, 5 minutes and may try to infer the purpose of the stop from the stop location and time. Shorter stops, such as delays at traffic lights, however would not be relevant for this appication. \n", "\n", "In the MovingPandas **TrajectoryStopDetector** implementation, a stop is detected if the movement stays within an area of specified size for at least the specified duration." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.core.display import display, HTML\n", "display(HTML(\"\"))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import geopandas as gpd\n", "from datetime import datetime, timedelta\n", "\n", "import sys\n", "sys.path.append(\"..\")\n", "import movingpandas as mpd\n", "print(mpd.__version__)\n", "\n", "import warnings\n", "warnings.simplefilter(\"ignore\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Loading Geolife Sample" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%time\n", "df = gpd.read_file('data/demodata_geolife.gpkg')\n", "df['t'] = pd.to_datetime(df['t'])\n", "df = df.set_index('t').tz_localize(None)\n", "print(\"Finished reading {} rows\".format(len(df)))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "traj_collection = mpd.TrajectoryCollection(df, 'trajectory_id')\n", "print(traj_collection)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Stop Detection with a SingleTrajectory" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%time\n", "my_traj = traj_collection.trajectories[0]\n", "stops = mpd.TrajectoryStopDetector(my_traj).get_stop_segments(min_duration=timedelta(seconds=60), max_diameter=100)\n", "len(stops)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "( my_traj.hvplot(title='Stops in Trajectory {}'.format(my_traj.id), line_width=7.0, tiles='CartoLight', color='slategray', width=700, height=700) * \n", " stops.hvplot( size=200, line_width=7.0, tiles=None, color='deeppink') *\n", " stops.get_start_locations().hvplot(geo=True, size=200, color='deeppink') )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%time\n", "split = mpd.StopSplitter(my_traj).split(min_duration=timedelta(seconds=60), max_diameter=100)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "( my_traj.hvplot(title='Stops in Trajectory {}'.format(my_traj.id), line_width=7.0, tiles='CartoLight', color='slategray', width=400, height=700) * \n", " stops.get_start_locations().hvplot(geo=True, size=200, color='deeppink') +\n", " split.hvplot(title='Trajectory {} split at stops'.format(my_traj.id), line_width=7.0, tiles='CartoLight', width=400, height=700) \n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for segment in split:\n", " print(segment)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Stop Detection for TrajectoryCollections\n", "\n", "The process is the same as for individual trajectories." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "%%time\n", "stops = mpd.TrajectoryStopDetector(traj_collection).get_stop_segments(min_duration=timedelta(seconds=60), max_diameter=100)\n", "len(stops)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "( traj_collection.hvplot(width=700, height=700, line_width=7.0, tiles='CartoLight', color='slategray') * \n", " stops.hvplot( size=200, line_width=7.0, tiles=None, color='deeppink') *\n", " stops.get_start_locations().hvplot(geo=True, size=200, color='deeppink') )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.7.8" } }, "nbformat": 4, "nbformat_minor": 4 }