In [8]:
import pandas as pd
import geopandas as gpd
import movingpandas as mpd
import datashader as ds
from hvplot import pandas
from holoviews import opts #, dim
from holoviews.element import tiles
from datetime import datetime, timedelta
In [9]:
mpd.show_versions()
MovingPandas 0.17.2 SYSTEM INFO ----------- python : 3.11.4 | packaged by Anaconda, Inc. | (main, Jul 5 2023, 13:47:18) [MSC v.1916 64 bit (AMD64)] executable : C:\Users\leoni\Programme\Miniconda\python.exe machine : Windows-10-10.0.22621-SP0 GEOS, GDAL, PROJ INFO --------------------- GEOS : None GEOS lib : None GDAL : 3.6.4 GDAL data dir: C:\Users\leoni\Programme\Miniconda\Lib\site-packages\fiona\gdal_data PROJ : 9.3.0 PROJ data dir: C:\Users\leoni\Programme\Miniconda\Lib\site-packages\pyproj\proj_dir\share\proj PYTHON DEPENDENCIES ------------------- geopandas : 0.14.1 pandas : 2.1.3 fiona : 1.9.5 numpy : 1.26.2 shapely : 2.0.2 rtree : 1.1.0 pyproj : 3.6.1 matplotlib : 3.8.1 mapclassify: 2.6.1 geopy : 2.4.0 holoviews : 1.18.1 hvplot : 0.9.0 geoviews : None stonesoup : None
In [10]:
opts.defaults(opts.Overlay(active_tools=['wheel_zoom'], frame_width=700, frame_height=300))
BG_TILES = tiles.CartoLight()
EVERID = 235
In [14]:
df = pd.read_csv('data/boat-positions.csv', parse_dates=True)
df['ais_pos_timestamp'] = pd.to_datetime(df['ais_pos_timestamp'], format='%d/%m/%Y %H:%M')
df
Out[14]:
ID | ais_pos_timestamp | longitude | latitude | |
---|---|---|---|---|
0 | 1 | 2021-03-20 00:22:00 | 32.32925 | 31.43860 |
1 | 1 | 2021-03-20 01:25:00 | 32.39860 | 31.40955 |
2 | 1 | 2021-03-20 02:07:00 | 32.37395 | 31.32413 |
3 | 1 | 2021-03-20 02:33:00 | 32.35152 | 31.24716 |
4 | 1 | 2021-03-20 02:53:00 | 32.33933 | 31.20590 |
... | ... | ... | ... | ... |
22282 | 256 | 2021-03-24 11:12:00 | 32.32908 | 31.19488 |
22283 | 256 | 2021-03-24 11:33:00 | 32.32909 | 31.19486 |
22284 | 256 | 2021-03-24 11:54:00 | 32.32910 | 31.19484 |
22285 | 256 | 2021-03-24 12:14:00 | 32.32908 | 31.19485 |
22286 | 256 | 2021-03-24 12:35:00 | 32.32909 | 31.19483 |
22287 rows × 4 columns
In [16]:
tmp = df.copy()
tmp.loc[:, 'x'], tmp.loc[:, 'y'] = ds.utils.lnglat_to_meters(tmp.longitude, tmp.latitude)
BG_TILES * tmp.hvplot.scatter(title='Density map', x='x', y='y', datashade=True)
Out[16]:
In [20]:
tc = mpd.TrajectoryCollection(df, 'ID', t='ais_pos_timestamp', x='longitude', y='latitude', crs=4326)
tc
Out[20]:
TrajectoryCollection with 250 trajectories
In [25]:
tc.to_traj_gdf().hvplot(title='All trajectories', geo=True, tiles='OSM')
Out[25]:
In [26]:
tc.get_trajectory(1)#.hvplot(geo=True)
Out[26]:
Trajectory 1 (2021-03-20 00:22:00 to 2021-03-20 13:08:00) | Size: 36 | Length: 195232.1m Bounds: (32.30417, 29.82953, 32.5869, 31.4386) LINESTRING (32.32925 31.4386, 32.3986 31.40955, 32.37395 31.32413, 32.35152 31.24716, 32.33933 31.20
In [27]:
tc.get_trajectory(1).hvplot(geo=True)
Out[27]:
In [28]:
tc.add_speed(units=('km','h'))
In [30]:
df.ID.max()
Out[30]:
256
In [31]:
traj_id = 15
tc.get_trajectory(traj_id).hvplot(title=f'Trajectory {traj_id}', c='speed', cmap='Viridis',
clim=(0,10), tiles='CartoLight')
Out[31]:
In [33]:
traj_id = EVERID
( tc.to_traj_gdf().hvplot(title=f'Trajectory {traj_id} on top of all other trajectories',
geo=True, tiles='OSM', color='orange', alpha=0.5) *
tc.get_trajectory(traj_id).hvplot(c='speed', cmap='Viridis', clim=(0,7), tiles=None) )
Out[33]:
In [34]:
( BG_TILES *
tmp.hvplot.scatter(title=f'Trajectory {traj_id} on top of density map',
x='x', y='y', datashade=True, cmap=['lightpink','hotpink','darkblue']) *
tc.get_trajectory(traj_id).hvplot(c='speed', cmap='Viridis', clim=(0,7), tiles=None) )
Out[34]:
In [35]:
stop_pts = mpd.TrajectoryStopDetector(tc, n_threads=3).get_stop_points(min_duration=timedelta(hours=3), max_diameter=1000)
stop_pts['duration_h'] = stop_pts['duration_s'] / 3600
stop_pts
Out[35]:
geometry | start_time | end_time | traj_id | duration_s | duration_h | |
---|---|---|---|---|---|---|
stop_id | ||||||
2_2021-03-21 08:29:00 | POINT (32.35567 31.21248) | 2021-03-21 08:29:00 | 2021-03-21 23:11:00 | 2 | 52920.0 | 14.700000 |
4_2021-03-23 22:23:00 | POINT (32.32796 31.39507) | 2021-03-23 22:23:00 | 2021-03-24 12:46:00 | 4 | 51780.0 | 14.383333 |
5_2021-03-20 09:47:00 | POINT (32.35727 31.21790) | 2021-03-20 09:47:00 | 2021-03-21 03:55:00 | 5 | 65280.0 | 18.133333 |
8_2021-03-23 06:15:00 | POINT (32.58077 30.00576) | 2021-03-23 06:15:00 | 2021-03-24 12:50:00 | 8 | 110100.0 | 30.583333 |
9_2021-03-20 02:07:00 | POINT (32.43236 30.30340) | 2021-03-20 02:07:00 | 2021-03-20 05:56:00 | 9 | 13740.0 | 3.816667 |
... | ... | ... | ... | ... | ... | ... |
249_2021-03-20 06:30:00 | POINT (32.34406 30.36822) | 2021-03-20 06:30:00 | 2021-03-20 14:09:00 | 249 | 27540.0 | 7.650000 |
250_2021-03-23 17:17:00 | POINT (32.53383 29.83297) | 2021-03-23 17:17:00 | 2021-03-24 12:21:00 | 250 | 68640.0 | 19.066667 |
251_2021-03-23 22:21:00 | POINT (32.35181 31.45093) | 2021-03-23 22:21:00 | 2021-03-24 12:48:00 | 251 | 52020.0 | 14.450000 |
255_2021-03-23 08:52:00 | POINT (32.57538 29.85072) | 2021-03-23 08:52:00 | 2021-03-24 11:14:00 | 255 | 94920.0 | 26.366667 |
256_2021-03-20 00:25:00 | POINT (32.32908 31.19485) | 2021-03-20 00:25:00 | 2021-03-24 12:35:00 | 256 | 389400.0 | 108.166667 |
258 rows × 6 columns
In [36]:
stop_pts.hvplot(title='Stops', geo=True, tiles='OSM', color='red', size='duration_h')
Out[36]:
In [37]:
( pd.DataFrame(stop_pts).hvplot.scatter(
title='Stop start & duration (in hours)', x='start_time', y='duration_h') *
pd.DataFrame(stop_pts[stop_pts['traj_id']==EVERID]).hvplot.scatter(
x='start_time', y='duration_h', color='red', size=200) )
Out[37]:
In [38]:
stop_pts[stop_pts.start_time > datetime(2021,3,23,5,0,0)]\
.sort_values('duration_s', ascending=False)\
.head(7)\
.style.background_gradient(cmap='Reds')
Out[38]:
geometry | start_time | end_time | traj_id | duration_s | duration_h | |
---|---|---|---|---|---|---|
stop_id | ||||||
235_2021-03-23 05:47:00 | POINT (32.58019 30.01763) | 2021-03-23 05:47:00 | 2021-03-24 12:52:00 | 235 | 111900.000000 | 31.083333 |
8_2021-03-23 06:15:00 | POINT (32.58077 30.00576) | 2021-03-23 06:15:00 | 2021-03-24 12:50:00 | 8 | 110100.000000 | 30.583333 |
168_2021-03-23 06:26:00 | POINT (32.58109 30.003) | 2021-03-23 06:26:00 | 2021-03-24 12:49:00 | 168 | 109380.000000 | 30.383333 |
124_2021-03-23 06:53:00 | POINT (32.588544999999996 29.77551) | 2021-03-23 06:53:00 | 2021-03-24 12:30:00 | 124 | 106620.000000 | 29.616667 |
81_2021-03-23 07:48:00 | POINT (32.57137 29.83667) | 2021-03-23 07:48:00 | 2021-03-24 12:33:00 | 81 | 103500.000000 | 28.750000 |
193_2021-03-23 08:04:00 | POINT (32.53971 29.92151) | 2021-03-23 08:04:00 | 2021-03-24 12:46:00 | 193 | 103320.000000 | 28.700000 |
54_2021-03-23 08:48:00 | POINT (32.58387 29.98875) | 2021-03-23 08:48:00 | 2021-03-24 12:51:00 | 54 | 100980.000000 | 28.050000 |
In [ ]: