Source code for pymove.visualization.folium

"""
Folium operations.

save_map,
create_base_map,
heatmap,
heatmap_with_time,
cluster,
faster_cluster,
plot_markers,
plot_trajectories,
plot_trajectory_by_id,
plot_trajectory_by_period,
plot_trajectory_by_day_week,
plot_trajectory_by_date,
plot_trajectory_by_hour,
plot_stops,
plot_bbox,
plot_points,
plot_poi,
plot_event,
plot_traj_timestamp_geo_json

"""
from __future__ import annotations

from datetime import date
from typing import Any, Sequence

import folium
import numpy as np
from folium import Map, plugins
from folium.plugins import FastMarkerCluster, HeatMap, HeatMapWithTime, MarkerCluster
from pandas import DataFrame

from pymove import PandasMoveDataFrame
from pymove.utils.constants import (
    COUNT,
    DATE,
    DATETIME,
    DAY,
    EVENT_POINT,
    HOUR,
    LATITUDE,
    LONGITUDE,
    PERIOD,
    POI_POINT,
    SITUATION,
    STOP,
    TILES,
    TRAJ_ID,
    USER_POINT,
)
from pymove.utils.datetime import str_to_datetime
from pymove.utils.log import progress_bar
from pymove.utils.visual import add_map_legend, cmap_hex_color, get_cmap


[docs]def save_map( move_data: DataFrame, filename: str, tiles: str = TILES[0], label_id: str = TRAJ_ID, cmap: str = 'Set1', return_map: bool = False ) -> Map | None: """ Save a visualization in a map in a new file. Parameters ---------- move_data : DataFrame Input trajectory data filename : Text Represents the filename path tiles : str, optional Represents the type_ of tile that will be used on the map, by default TILES[0] label_id : str, optional Represents column name of trajectory id, by default TRAJ_ID cmap : str, optional Color map to use, by default 'Set1' return_map : bool, optional Represents the Colormap, by default False Returns ------- Map folium map or None Examples -------- >>> from pymove.visualization.folium import save_map >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> save_map(df, filename='test.map') """ map_ = folium.Map(tiles=tiles) map_.fit_bounds( [ [move_data[LATITUDE].min(), move_data[LONGITUDE].min()], [move_data[LATITUDE].max(), move_data[LONGITUDE].max()], ] ) ids = move_data[label_id].unique() cmap_ = get_cmap(cmap) num = cmap_.N for id_ in ids: id_index = np.where(ids == id_)[0][0] move_df = move_data[move_data[label_id] == id_] points_ = [ (point[0], point[1]) for point in move_df[[LATITUDE, LONGITUDE]].values ] color_ = cmap_hex_color(cmap_, (id_index % num)) folium.PolyLine(points_, weight=3, color=color_).add_to(map_) map_.save(filename) if return_map: return map_
[docs]def create_base_map( move_data: DataFrame, lat_origin: float | None = None, lon_origin: float | None = None, tile: str = TILES[0], default_zoom_start: float = 12, ) -> Map: """ Generates a folium map. Parameters ---------- move_data : DataFrame Input trajectory data lat_origin : float, optional Represents the latitude which will be the center of the map, by default None lon_origin : float, optional Represents the longitude which will be the center of the map, by default None tile : str, optional Represents the map tiles, by default TILES[0] default_zoom_start : float, optional Represents the zoom which will be the center of the map, by default 12 Returns ------- Map a folium map Examples -------- >>> from pymove.visualization.folium import create_base_map >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> create_base_map(move_df) """ if lat_origin is None and lon_origin is None: lat_origin = move_data[LATITUDE].median() lon_origin = move_data[LONGITUDE].median() base_map = folium.Map( location=[lat_origin, lon_origin], control_scale=True, zoom_start=default_zoom_start, tiles=tile ) return base_map
[docs]def heatmap( move_data: DataFrame, n_rows: int | None = None, lat_origin: float | None = None, lon_origin: float | None = None, zoom_start: float = 12, radius: float = 8, base_map: Map | None = None, tile: str = TILES[0], save_as_html: bool = False, filename: str = 'heatmap.html', ) -> Map: """ Generate visualization of Heat Map using folium plugin. Parameters ---------- move_data : DataFrame Input trajectory data n_rows : int, optional Represents number of data rows that are will plot, by default None lat_origin : float, optional Represents the latitude which will be the center of the map, by default None lon_origin : float, optional Represents the longitude which will be the center of the map, by default None zoom_start : float, optional Initial zoom level for the map, by default 12 radius : float, optional Radius of each “point” of the heatmap, by default 8 base_map : Map, optional Represents the folium map. If not informed, a new map is generated using the function create_base_map(), with the lat_origin, lon_origin and zoom_start, by default None tile : str, optional Represents the map tiles, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False filename : str, optional Represents the file name of new file .html, by default 'heatmap.html' Returns ------- Map folium Map Examples -------- >>> from pymove.visualization.folium import heatmap >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> heatmap(move_df) """ if base_map is None: base_map = create_base_map( move_data, lat_origin, lon_origin, tile=tile, default_zoom_start=zoom_start, ) if n_rows is None: n_rows = move_data.shape[0] move_data[COUNT] = 1 HeatMap( data=move_data.iloc[:n_rows][[LATITUDE, LONGITUDE, COUNT]] .groupby([LATITUDE, LONGITUDE]) .sum() .reset_index() .values.tolist(), radius=radius ).add_to(base_map) move_data.drop(columns=COUNT, inplace=True) if save_as_html: base_map.save(outfile=filename) return base_map
[docs]def heatmap_with_time( move_data: DataFrame, n_rows: int | None = None, lat_origin: float | None = None, lon_origin: float | None = None, zoom_start: float = 12, radius: float = 8, min_opacity: float = 0.5, max_opacity: float = 0.8, base_map: Map | None = None, tile: str = TILES[0], save_as_html: bool = False, filename: str = 'heatmap_time.html', ) -> Map: """ Generate visualization of Heat Map using folium plugin. Parameters ---------- move_data : DataFrame Input trajectory data n_rows : int, optional Represents number of data rows that are will plot, by default None lat_origin : float, optional Represents the latitude which will be the center of the map, by default None lon_origin : float, optional Represents the longitude which will be the center of the map, by default None zoom_start : float, optional Initial zoom level for the map, by default 12 radius : float, optional Radius of each “point” of the heatmap, by default 8 min_opacity: float, optional Minimum heat opacity, by default 0.5. max_opacity: float, optional Maximum heat opacity, by default 0.8. base_map : Map, optional Represents the folium map. If not informed, a new map is generated using the function create_base_map(), with the lat_origin, lon_origin and zoom_start, by default None tile : str, optional Represents the map tiles, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False filename : str, optional Represents the file name of new file .html, by default 'heatmap_time.html' Returns ------- Map folium Map Examples -------- >>> from pymove.visualization.folium import heatmap_with_time >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> heatmap_with_time(move_df) """ if base_map is None: base_map = create_base_map( move_data, lat_origin, lon_origin, tile=tile, default_zoom_start=zoom_start, ) if n_rows is None: n_rows = move_data.shape[0] move_data = move_data.iloc[:n_rows].copy() move_data[COUNT] = 1 move_data[HOUR] = move_data[DATETIME].apply(lambda x: x.hour) move_data_hour_list = [] for hour in move_data[HOUR].sort_values().unique(): move_data_hour_list.append( move_data.loc[move_data.hour == hour, [LATITUDE, LONGITUDE, COUNT]] .groupby([LATITUDE, LONGITUDE]) .sum() .reset_index() .values.tolist() ) HeatMapWithTime( move_data_hour_list, radius=radius, gradient={0.2: 'blue', 0.4: 'lime', 0.6: USER_POINT, 1: 'red'}, min_opacity=min_opacity, max_opacity=max_opacity, use_local_extrema=True ).add_to(base_map) move_data.drop(columns=[COUNT, HOUR], inplace=True) if save_as_html: base_map.save(outfile=filename) return base_map
[docs]def cluster( move_data: DataFrame, n_rows: int | None = None, lat_origin: float | None = None, lon_origin: float | None = None, zoom_start: float = 12, base_map: Map | None = None, tile: str = TILES[0], save_as_html: bool = False, filename: str = 'cluster.html', ) -> Map: """ Generate visualization of Heat Map using folium plugin. Parameters ---------- move_data : DataFrame Input trajectory data n_rows : int, optional Represents number of data rows that are will plot, by default None lat_origin : float, optional Represents the latitude which will be the center of the map, by default None lon_origin : float, optional Represents the longitude which will be the center of the map, by default None zoom_start : float, optional Initial zoom level for the map, by default 12 radius : float, optional Radius of each “point” of the heatmap, by default 8 base_map : Map, optional Represents the folium map. If not informed, a new map is generated using the function create_base_map(), with the lat_origin, lon_origin and zoom_start, by default None tile : str, optional Represents the map tiles, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False filename : str, optional Represents the file name of new file .html, by default 'cluster.html' Returns ------- Map folium Map Examples -------- >>> from pymove.visualization.folium import cluster >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> cluster(move_df) """ if base_map is None: base_map = create_base_map( move_data, lat_origin, lon_origin, tile=tile, default_zoom_start=zoom_start, ) if n_rows is None: n_rows = move_data.shape[0] mc = MarkerCluster() for row in move_data.iloc[:n_rows].iterrows(): pop = ( '<b>Latitude:</b> ' + str(row[1][LATITUDE]) + '\n<b>Longitude:</b> ' + str(row[1][LONGITUDE]) + '\n<b>Datetime:</b> ' + str(row[1][DATETIME]) ) mc.add_child( folium.Marker( location=[row[1][LATITUDE], row[1][LONGITUDE]], popup=pop ) ) base_map.add_child(mc) if save_as_html: base_map.save(outfile=filename) return base_map
[docs]def faster_cluster( move_data: DataFrame, n_rows: int | None = None, lat_origin: float | None = None, lon_origin: float | None = None, zoom_start: float = 12, base_map: Map | None = None, tile: str = TILES[0], save_as_html: bool = False, filename: str = 'faster_cluster.html', ) -> Map: """ Generate visualization of Heat Map using folium plugin. Parameters ---------- move_data : DataFrame Input trajectory data n_rows : int, optional Represents number of data rows that are will plot, by default None lat_origin : float, optional Represents the latitude which will be the center of the map, by default None lon_origin : float, optional Represents the longitude which will be the center of the map, by default None zoom_start : float, optional Initial zoom level for the map, by default 12 radius : float, optional Radius of each “point” of the heatmap, by default 8 base_map : Map, optional Represents the folium map. If not informed, a new map is generated using the function create_base_map(), with the lat_origin, lon_origin and zoom_start, by default None tile : str, optional Represents the map tiles, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False filename : str, optional Represents the file name of new file .html, by default 'faster_cluster.html' Returns ------- Map folium Map Examples -------- >>> from pymove.visualization.folium import faster_cluster >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> faster_cluster(move_df) """ if base_map is None: base_map = create_base_map( move_data, lat_origin, lon_origin, tile=tile, default_zoom_start=zoom_start, ) if n_rows is None: n_rows = move_data.shape[0] callback = """\ function (row) { var marker; marker = L.circle(new L.LatLng(row[0], row[1]), {color:'red'}); return marker; }; """ FastMarkerCluster( move_data.iloc[:n_rows][[LATITUDE, LONGITUDE]].values.tolist(), callback=callback, ).add_to(base_map) if save_as_html: base_map.save(outfile=filename) return base_map
[docs]def plot_markers( move_data: DataFrame, n_rows: int | None = None, lat_origin: float | None = None, lon_origin: float | None = None, zoom_start: float = 12, base_map: Map | None = None, tile: str = TILES[0], save_as_html: bool = False, filename: str = 'markers.html', ) -> Map: """ Generate visualization of Heat Map using folium plugin. Parameters ---------- move_data : DataFrame Input trajectory data n_rows : int, optional Represents number of data rows that are will plot, by default None lat_origin : float, optional Represents the latitude which will be the center of the map, by default None lon_origin : float, optional Represents the longitude which will be the center of the map, by default None zoom_start : float, optional Initial zoom level for the map, by default 12 radius : float, optional Radius of each “point” of the heatmap, by default 8 base_map : Map, optional Represents the folium map. If not informed, a new map is generated using the function create_base_map(), with the lat_origin, lon_origin and zoom_start, by default None tile : str, optional Represents the map tiles, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False filename : str, optional Represents the file name of new file .html, by default 'markers.html' Returns ------- Map folium Map Examples -------- >>> from pymove.visualization.folium import plot_markers >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> plot_markers(move_df) """ if base_map is None: base_map = create_base_map( move_data, lat_origin, lon_origin, tile=tile, default_zoom_start=zoom_start, ) if n_rows is None: n_rows = move_data.shape[0] for i, row in enumerate(move_data.iloc[:n_rows].iterrows()): if i == 0: se = '<b>START</b>\n' color = 'green' elif i == n_rows - 1: se = '<b>END\ns</b>\n' color = 'red' else: se = '' color = 'blue' pop = ( se + '<b>Latitude:</b> ' + str(row[1][LATITUDE]) + '\n<b>Longitude:</b> ' + str(row[1][LONGITUDE]) + '\n<b>Datetime:</b> ' + str(row[1][DATETIME]) ) folium.Marker( location=[row[1][LATITUDE], row[1][LONGITUDE]], color=color, clustered_marker=True, popup=pop, icon=folium.Icon(color=color) ).add_to(base_map) if save_as_html: base_map.save(outfile=filename) return base_map
def _filter_and_generate_colors( move_data: DataFrame, id_: int | None = None, n_rows: int | None = None, color: str | list[str] | None = None, color_by_id: dict | None = None ) -> tuple[DataFrame, list[tuple[Any, Any]]]: """ Filters the dataframe and generate colors for folium map. Parameters ---------- move_data : DataFrame Input trajectory data. id_: int, optional The TRAJ_ID's to be plotted, by default None n_rows : int, optional Represents number of data rows that are will plot, by default None. color: str, optional The color of the trajectory, of each trajectory or a colormap, by default None color_by_id: dict, optional A dictionary where the key is the trajectory id and value is a color(str), by default None. Returns ------- DataFrame Filtered trajectories list of tuples list containing a combination of id and color Examples -------- >>> from pymove.visualization.folium import _filter_and_generate_colors >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 2 4 39.984217 116.319422 2008-10-23 05:53:21 2 >>> df, colors = _filter_and_generate_colors(move_df) >>> df lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 2 4 39.984217 116.319422 2008-10-23 05:53:21 2 >>> colors [(1, '#e41a1c'), (2, '#377eb8')] """ if n_rows is None: n_rows = move_data.shape[0] if id_ is not None: mv_df = move_data[move_data[TRAJ_ID] == id_].head(n_rows)[ [LATITUDE, LONGITUDE, DATETIME, TRAJ_ID] ] if not len(mv_df): raise IndexError('No user with id %s in dataframe' % id_) else: mv_df = move_data.head(n_rows)[ [LATITUDE, LONGITUDE, DATETIME, TRAJ_ID] ] if id_ is not None: if color is None: color = 'black' items = [(id_, color)] else: if color is None: color = 'Set1' ids = mv_df[TRAJ_ID].unique() if isinstance(color, str): try: cmap_ = get_cmap(color) num = cmap_.N colors = [ cmap_hex_color(cmap_, (i % num)) for i, _ in enumerate(ids) ] diff = (len(ids) // len(colors)) + 1 colors *= diff except ValueError: colors = [color] else: colors = color[:] items = [*zip(ids, colors)] if color_by_id is not None: keys = color_by_id.keys() for key in keys: for count, item in enumerate(items): if str(key) == str(item[0]): items[count] = (item[0], color_by_id[key]) return mv_df, items def _filter_generated_feature( move_data: DataFrame, feature: str, values: Any ) -> DataFrame: """ Filters the values from the dataframe. Parameters ---------- move_data : DataFrame Input trajectory data. feature: str Name of the feature value: any value of the feature Returns ------- dataframe filtered dataframe Examples -------- >>> from pymove.visualization.folium import _filter_generated_feature >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> _filter_generated_feature(move_df, feature='lat', values=[39.984198]) lat lon datetime id 1 39.984198 116.319322 2008-10-23 05:53:06 1 >>> _filter_generated_feature(move_df, feature='lon', values=[116.319236]) lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 """ if len(values) == 1: mv_df = move_data[move_data[feature] == values[0]] else: mv_df = move_data[ (move_data[feature] >= values[0]) & (move_data[feature] <= values[1]) ] if not len(mv_df): raise KeyError('No %s found in dataframe' % feature) return mv_df def _add_begin_end_markers_to_map( move_data: DataFrame, base_map: Map, color: str | None = None, _id: int | None = None ): """ Adds markers to the beggining and end of a trajectory. Adds a green marker to beginning of the trajectory and a red marker to the end of the trajectory. Parameters ---------- move_data : DataFrane Input trajectory data. base_map : Map, optional Represents the folium map. If not informed, a new map is generated. color : str, optional Color of the markers, by default None id: int, optional Id of the trajectory, by default None Examples -------- >>> from pymove.visualization.folium import _add_begin_end_markers_to_map >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> map = create_base_map(move_df) >>> _add_begin_end_markers_to_map(move_df, map) """ points = folium.map.FeatureGroup( 'The start and end points of trajectory {}'.format(_id or '') ) folium.Marker( location=[move_data.iloc[0][LATITUDE], move_data.iloc[0][LONGITUDE]], color='green', clustered_marker=True, popup='Início', icon=plugins.BeautifyIcon( icon='play', icon_shape='marker', background_color=color or 'green' ) ).add_to(points) folium.Marker( location=[move_data.iloc[-1][LATITUDE], move_data.iloc[-1][LONGITUDE]], color='red', clustered_marker=True, popup='Fim', icon=plugins.BeautifyIcon( icon='times-circle', icon_shape='marker', background_color=color or 'red' ) ).add_to(points) base_map.add_child(points) def _add_trajectories_to_map( move_data: DataFrame, items: Sequence[tuple], base_map: Map, legend: bool = True, save_as_html: bool = True, filename: str = 'map.html', ): """ Adds a trajectory to a folium map with begin and end markers. Parameters ---------- move_data : DataFrame Input trajectory data. base_map : Map Represents the folium map. If not informed, a new map is generated. legend: bool Whether to add a legend to the map, by default True save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False. filename : str, optional Represents the file name of new file .html, by default 'map.html'. Examples -------- >>> from pymove.visualization.folium import _add_trajectories_to_map >>> move_df lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 3 39.988118 116.326672 2008-10-25 14:39:19 5 4 39.987965 116.326675 2008-10-25 14:39:24 5 >>> _add_trajectories_to_map( >>> move_data=move_df, >>> base_map=map1, >>> items=[(1, 'red'), [5, 'green']] >>> ) """ for _id, color in items: mv = move_data[move_data[TRAJ_ID] == _id] _add_begin_end_markers_to_map(mv, base_map, color, _id) folium.PolyLine( mv[[LATITUDE, LONGITUDE]], color=color, weight=2.5, opacity=1 ).add_to(base_map) if legend: add_map_legend(base_map, 'Color by user ID', items) folium.map.LayerControl().add_to(base_map) if save_as_html: base_map.save(outfile=filename)
[docs]def plot_trajectories( move_data: DataFrame, n_rows: int | None = None, lat_origin: float | None = None, lon_origin: float | None = None, zoom_start: float = 12, legend: bool = True, base_map: Map | None = None, tile: str = TILES[0], save_as_html: bool = False, color: str | list[str] | None = None, color_by_id: dict | None = None, filename: str = 'plot_trajectories.html', ) -> Map: """ Generate visualization of all trajectories with folium. Parameters ---------- move_data : DataFrame Input trajectory data. n_rows : int, optional Represents number of data rows that are will plot, by default None. lat_origin : float, optional Represents the latitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. lon_origin : float, optional Represents the longitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. zoom_start : int, optional Initial zoom level for the map, by default 12. legend: boolean Whether to add a legend to the map, by default True base_map : folium.folium.Map, optional Represents the folium map. If not informed, a new map is generated using the function create_base_map(), with the lat_origin, lon_origin and zoom_start, by default None. tile : str, optional Represents the map tiles, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False. color : str, list, optional Represents line colors of visualization. Can be a single color name, a list of colors or a colormap name, by default None. color_by_id: dict, optional A dictionary where the key is the trajectory id and value is a color(str), by default None. filename : str, optional Represents the file name of new file .html, by default 'plot_trajectory.html'. Returns ------- Map a folium map with visualization. Examples -------- >>> from pymove.visualization.folium import plot_trajectories >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> plot_trajectories(move_df) """ if base_map is None: base_map = create_base_map( move_data, lat_origin, lon_origin, tile=tile, default_zoom_start=zoom_start, ) mv_df, items = _filter_and_generate_colors( move_data, n_rows=n_rows, color=color, color_by_id=color_by_id ) _add_trajectories_to_map( mv_df, items, base_map, legend, save_as_html, filename ) return base_map
[docs]def plot_trajectory_by_id( move_data: DataFrame, id_: int, n_rows: int | None = None, lat_origin: float | None = None, lon_origin: float | None = None, zoom_start: float = 12, legend: bool = True, base_map: Map | None = None, tile: str = TILES[0], save_as_html: bool = False, color: str | list[str] | None = None, filename: str = 'plot_trajectories.html', ) -> Map: """ Generate visualization of all trajectories with folium. Parameters ---------- move_data : DataFrame Input trajectory data id_: int Trajectory id to plot n_rows : int, optional Represents number of data rows that are will plot, by default None. lat_origin : float, optional Represents the latitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. lon_origin : float, optional Represents the longitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. zoom_start : int, optional Initial zoom level for the map, by default 12. legend: boolean Whether to add a legend to the map, by default True base_map : folium.folium.Map, optional Represents the folium map. If not informed, a new map is generated using the function create_base_map(), with the lat_origin, lon_origin and zoom_start, by default None. tile : str, optional Represents the map tiles, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False. color : str, list, optional Represents line colors of visualization. Can be a single color name, a list of colors or a colormap name, by default None. filename : str, optional Represents the file name of new file .html, by default 'plot_trajectory_by_id.html'. Returns ------- Map a folium map with visualization Raises ------ IndexError If there is no user with the id passed Examples -------- >>> from pymove.visualization.folium import plot_trajectory_by_id >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 2 4 39.984217 116.319422 2008-10-23 05:53:21 2 >>> plot_trajectory_by_id(move_df, id_=1) """ if base_map is None: base_map = create_base_map( move_data, lat_origin, lon_origin, tile=tile, default_zoom_start=zoom_start, ) mv_df, items = _filter_and_generate_colors(move_data, id_, n_rows, color) _add_trajectories_to_map( mv_df, items, base_map, legend, save_as_html, filename ) return base_map
[docs]def plot_trajectory_by_period( move_data: PandasMoveDataFrame, period: str, id_: int | None = None, n_rows: int | None = None, lat_origin: float | None = None, lon_origin: float | None = None, zoom_start: float = 12, legend: bool = True, base_map: Map | None = None, tile: str = TILES[0], save_as_html: bool = False, color: str | list[str] | None = None, color_by_id: dict | None = None, filename: str = 'plot_trajectories_by_period.html', ) -> Map: """ Generate visualization of all trajectories with folium. Parameters ---------- move_data : DataFrame Input trajectory data period: str Period of the day id_: int Trajectory id to plot, by default None n_rows : int, optional Represents number of data rows that are will plot, by default None. lat_origin : float, optional Represents the latitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. lon_origin : float, optional Represents the longitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. zoom_start : int, optional Initial zoom level for the map, by default 12. legend: boolean Whether to add a legend to the map, by default True base_map : folium.folium.Map, optional Represents the folium map. If not informed, a new map is generated using the function create_base_map(), with the lat_origin, lon_origin and zoom_start, by default None. tile : str, optional Represents the map tiles, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False. color : str, list, optional Represents line colors of visualization. Can be a single color name, a list of colors or a colormap name, by default None. color_by_id: dict, optional A dictionary where the key is the trajectory id and value is a color, by default None. filename : str, optional Represents the file name of new file .html, by default 'plot_trajectories_by_period.html'. Returns ------- Map a folium map with visualization Raises ------ KeyError If period value is not found in dataframe IndexError If there is no user with the id passed Examples -------- >>> from pymove.visualization.folium import plot_trajectory_by_period >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> plot_trajectory_by_period(move_df, period='Early morning') """ if base_map is None: base_map = create_base_map( move_data, lat_origin, lon_origin, tile=tile, default_zoom_start=zoom_start, ) columns = move_data.columns if PERIOD not in move_data: move_data.generate_time_of_day_features() mv_df = _filter_generated_feature(move_data, PERIOD, [period]) mv_df, items = _filter_and_generate_colors(mv_df, id_, n_rows, color, color_by_id) _add_trajectories_to_map( mv_df, items, base_map, legend, save_as_html, filename ) to_drop = list(set(move_data.columns) - set(columns)) move_data.drop(columns=to_drop, inplace=True) return base_map
[docs]def plot_trajectory_by_day_week( move_data: PandasMoveDataFrame, day_week: str, id_: int | None = None, n_rows: int | None = None, lat_origin: float | None = None, lon_origin: float | None = None, zoom_start: float = 12, legend: bool = True, base_map: Map | None = None, tile: str = TILES[0], save_as_html: bool = False, color: str | list[str] | None = None, color_by_id: dict | None = None, filename: str = 'plot_trajectories_by_day_week.html', ) -> Map: """ Generate visualization of all trajectories with folium. Parameters ---------- move_data : DataFrame Input trajectory data day_week: str Day of the week id_: int Trajectory id to plot, by default None n_rows : int, optional Represents number of data rows that are will plot, by default None. lat_origin : float, optional Represents the latitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. lon_origin : float, optional Represents the longitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. zoom_start : int, optional Initial zoom level for the map, by default 12. legend: boolean Whether to add a legend to the map, by default True base_map : folium.folium.Map, optional Represents the folium map. If not informed, a new map is generated using the function create_base_map(), with the lat_origin, lon_origin and zoom_start, by default None. tile : str, optional Represents the map tiles, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False. color : str, list, optional Represents line colors of visualization. Can be a single color name, a list of colors or a colormap name, by default None. color_by_id: dict, optional A dictionary where the key is the trajectory id and value is a color, by default None. filename : str, optional Represents the file name of new file .html, by default 'plot_trajectories_by_day_week.html'. Returns ------- Map a folium map with visualization Raises ------ KeyError If period value is not found in dataframe IndexError If there is no user with the id passed Examples -------- >>> from pymove.visualization.folium import plot_trajectory_by_day_week >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> plot_trajectory_by_day_week(move_df, day_week='Friday') """ if base_map is None: base_map = create_base_map( move_data, lat_origin, lon_origin, tile=tile, default_zoom_start=zoom_start, ) columns = move_data.columns if DAY not in move_data: move_data.generate_day_of_the_week_features() mv_df = _filter_generated_feature(move_data, DAY, [day_week]) mv_df, items = _filter_and_generate_colors(mv_df, id_, n_rows, color, color_by_id) _add_trajectories_to_map( mv_df, items, base_map, legend, save_as_html, filename ) to_drop = list(set(move_data.columns) - set(columns)) move_data.drop(columns=to_drop, inplace=True) return base_map
[docs]def plot_trajectory_by_date( move_data: PandasMoveDataFrame, start_date: str | date, end_date: str | date, id_: int | None = None, n_rows: int | None = None, lat_origin: float | None = None, lon_origin: float | None = None, zoom_start: float = 12, legend: bool = True, base_map: Map | None = None, tile: str = TILES[0], save_as_html: bool = False, color: str | list[str] | None = None, color_by_id: dict | None = None, filename: str = 'plot_trajectories_by_date.html', ) -> Map: """ Generate visualization of all trajectories with folium. Parameters ---------- move_data : DataFrame Input trajectory data start_date : str Represents start date of time period. end_date : str Represents end date of time period. id_: int, optional Trajectory id to plot, by default None n_rows : int, optional Represents number of data rows that are will plot, by default None. lat_origin : float, optional Represents the latitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. lon_origin : float, optional Represents the longitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. zoom_start : int, optional Initial zoom level for the map, by default 12. legend: boolean Whether to add a legend to the map, by default True base_map : folium.folium.Map, optional Represents the folium map. If not informed, a new map is generated using the function create_base_map(), with the lat_origin, lon_origin and zoom_start, by default None. tile : str, optional Represents the map tiles, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False. color : str, list, optional Represents line colors of visualization. Can be a single color name, a list of colors or a colormap name, by default None. color_by_id: dict, optional A dictionary where the key is the trajectory id and value is a color, by default None. filename : str, optional Represents the file name of new file .html, by default 'plot_trajectories_by_date.html'. Returns ------- Map a folium map with visualization Raises ------ KeyError If period value is not found in dataframe IndexError If there is no user with the id passed Examples -------- >>> from pymove.visualization.folium import plot_trajectory_by_date >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> plot_trajectory_by_date( >>> move_df, >>> start_date='2008-10-23 05:53:05', >>> end_date='2008-10-23 23:43:56' >>> ) """ if base_map is None: base_map = create_base_map( move_data, lat_origin, lon_origin, tile=tile, default_zoom_start=zoom_start, ) if isinstance(start_date, str): start_date = str_to_datetime(start_date).date() if isinstance(end_date, str): end_date = str_to_datetime(end_date).date() columns = move_data.columns if DATE not in move_data: move_data.generate_date_features() mv_df = _filter_generated_feature(move_data, DATE, [start_date, end_date]) mv_df, items = _filter_and_generate_colors(mv_df, id_, n_rows, color, color_by_id) _add_trajectories_to_map( mv_df, items, base_map, legend, save_as_html, filename ) to_drop = list(set(move_data.columns) - set(columns)) move_data.drop(columns=to_drop, inplace=True) return base_map
[docs]def plot_trajectory_by_hour( move_data: PandasMoveDataFrame, start_hour: str, end_hour: str, id_: int | None = None, n_rows: int | None = None, lat_origin: float | None = None, lon_origin: float | None = None, zoom_start: float = 12, legend: bool = True, base_map: Map | None = None, tile: str = TILES[0], save_as_html: bool = False, color: str | list[str] | None = None, color_by_id: dict | None = None, filename: str = 'plot_trajectories_by_hour.html', ) -> Map: """ Generate visualization of all trajectories with folium. Parameters ---------- move_data : DataFrame Input trajectory data start_hour : str Represents start hour of time period. end_hour : str Represents end hour of time period. id_: int, optional Trajectory id to plot, by default None n_rows : int, optional Represents number of data rows that are will plot, by default None. lat_origin : float, optional Represents the latitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. lon_origin : float, optional Represents the longitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. zoom_start : int, optional Initial zoom level for the map, by default 12. legend: boolean Whether to add a legend to the map, by default True base_map : folium.folium.Map, optional Represents the folium map. If not informed, a new map is generated using the function create_base_map(), with the lat_origin, lon_origin and zoom_start, by default None. tile : str, optional Represents the map tiles, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False. color : str, list, optional Represents line colors of visualization. Can be a single color name, a list of colors or a colormap name, by default None. color_by_id: dict, optional A dictionary where the key is the trajectory id and value is a color, by default None. filename : str, optional Represents the file name of new file .html, by default 'plot_trajectories_by_hour.html'. Returns ------- Map a folium map with visualization Raises ------ KeyError If period value is not found in dataframe IndexError If there is no user with the id passed Examples -------- >>> from pymove.visualization.folium import plot_trajectory_by_hour >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> plot_trajectory_by_hour(move_df, start_hour=4, end_hour=6) """ if base_map is None: base_map = create_base_map( move_data, lat_origin, lon_origin, tile=tile, default_zoom_start=zoom_start, ) columns = move_data.columns if HOUR not in move_data: move_data.generate_hour_features() mv_df = _filter_generated_feature(move_data, HOUR, [start_hour, end_hour]) mv_df, items = _filter_and_generate_colors(mv_df, id_, n_rows, color, color_by_id) _add_trajectories_to_map( mv_df, items, base_map, legend, save_as_html, filename ) to_drop = list(set(move_data.columns) - set(columns)) move_data.drop(columns=to_drop, inplace=True) return base_map
[docs]def plot_stops( move_data: PandasMoveDataFrame, radius: float = 0, weight: float = 3, id_: int | None = None, n_rows: int | None = None, lat_origin: float | None = None, lon_origin: float | None = None, zoom_start: float = 12, legend: bool = True, base_map: Map | None = None, tile: str = TILES[0], save_as_html: bool = False, color: str | list[str] | None = None, filename: str = 'plot_stops.html', ) -> Map: """ Generate visualization of all trajectories with folium. Parameters ---------- move_data : DataFrame Input trajectory data radius : float, optional The radius value is used to determine if a segment is a stop. If the value of the point in target_label is greater than radius, the segment is a stop, by default 0 weight: float, optional Stroke width in pixels, by default 3 id_: int, optional Trajectory id to plot, by default None n_rows : int, optional Represents number of data rows that are will plot, by default None. lat_origin : float, optional Represents the latitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. lon_origin : float, optional Represents the longitude which will be the center of the map. If not entered, the first data from the dataset is used, by default None. zoom_start : int, optional Initial zoom level for the map, by default 12. legend: boolean Whether to add a legend to the map, by default True base_map : folium.folium.Map, optional Represents the folium map. If not informed, a new map is generated using the function create_base_map(), with the lat_origin, lon_origin and zoom_start, by default None. tile : str, optional Represents the map tiles, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False. color : str, list, optional Represents line colors of visualization. Can be a single color name, a list of colors or a colormap name, by default None. filename : str, optional Represents the file name of new file .html, by default 'plot_stops.html'. Returns ------- Map a folium map with visualization Raises ------ KeyError If period value is not found in dataframe IndexError If there is no user with the id passed Examples -------- >>> from pymove.visualization.folium import plot_stops >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> plot_stops(move_df) """ if base_map is None: base_map = create_base_map( move_data, lat_origin, lon_origin, tile=tile, default_zoom_start=zoom_start, ) columns = move_data.columns if SITUATION not in move_data: move_data.generate_move_and_stop_by_radius(radius=radius) mv_df = _filter_generated_feature(move_data, SITUATION, STOP) mv_df, items = _filter_and_generate_colors(mv_df, id_, n_rows, color) for _id, color in items: for stop in mv_df[mv_df[TRAJ_ID] == _id].iterrows(): base_map.add_child( folium.Circle( (stop[1][LATITUDE], stop[1][LONGITUDE]), color=color, weight=weight, radius=40, opacity=0.5, popup=stop[1][DATETIME], fill_color=color, fill_opacity=0.5, ) ) if legend: add_map_legend(base_map, 'Color by user ID', items) if save_as_html: base_map.save(outfile=filename) to_drop = list(set(move_data.columns) - set(columns)) move_data.drop(columns=to_drop, inplace=True) return base_map
[docs]def plot_bbox( bbox_tuple: tuple[float, float, float, float], base_map: Map | None = None, tiles: str = TILES[0], color: str = 'red', save_as_html: bool = False, filename: str = 'bbox.html' ) -> Map: """ Plots a bbox using Folium. Parameters ---------- bbox_tuple : tuple. Represents a bound box, that is a tuple of 4 values with the min and max limits of latitude e longitude. base_map: Folium map, optional A folium map to plot the trajectories. If None a map will be created, by default None. tiles : str, optional by default TILES[0] color : str, optional Represents color of lines on map, by default 'red'. file : str, optional Represents filename, by default 'bbox.html'. save_map: Boolean, optional Wether to save the bbox folium map, by default False. Returns ------- Map folium map with bounding box Examples -------- >>> from pymove.visualization.folium import plot_bbox >>> plot_bbox((39.984094,116.319236,39.997535,116.196345)) """ if base_map is None: base_map = folium.Map(tiles=tiles) base_map.fit_bounds( [[bbox_tuple[0], bbox_tuple[1]], [bbox_tuple[2], bbox_tuple[3]]] ) points_ = [ (bbox_tuple[0], bbox_tuple[1]), (bbox_tuple[0], bbox_tuple[3]), (bbox_tuple[2], bbox_tuple[3]), (bbox_tuple[2], bbox_tuple[1]), (bbox_tuple[0], bbox_tuple[1]), ] polygon = folium.PolyLine(points_, weight=3, color=color) polygon.add_to(base_map) if save_as_html: base_map.save(filename) return base_map
def _format_tags(line: list | dict, slice_: list) -> str: """ Create or format tags. Parameters ---------- line: Line to add a tag. slice_: Tag interval. Returns ------- str: formatted html tag Examples -------- >>> from pymove.visualization.folium import _format_tags, plot_points >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> _format_tags( >>> line={ >>> 'lat': 39.984094, >>> 'lon': 116.319236, >>> 'datetime': '2008-10-23 05:53:05', >>> 'id': 1 >>> }, >>> slice_=['lat', 'lon', 'datetime', 'id'] >>> ) lat: 39.984094<br/>lon: 116.319236<br/>datetime: 2008-10-23 05:53:05<br/>id: 1 """ map_formated_tags = map(lambda tag: f'{tag}: {line[tag]}', slice_) return '<br/>'.join(map_formated_tags) def _circle_maker( iter_tuple: DataFrame, user_lat: str, user_lon: str, slice_tags: list, user_point: str, radius: float, map_: Map ): """ Return a circle. Parameters ---------- iter_tuple: DataFrame iter_tuple. user_lat: str. Latitude column name. user_lon: str. Longitude column name. slice_tags: list or iterable user_point: str. Point color. radius: float. radius size. map_: Folium map. Examples -------- >>> from pymove.visualization.folium import _circle_maker >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> row = move_df.iloc[0] >>> iter_tuple = (0, row) >>> user_lat = 'lat' >>> user_lon = 'lon' >>> slice_tags = row.keys() >>> user_point = 'pink' >>> radius = 10 >>> map_ = create_base_map(move_df) >>> _circle_maker( >>> iter_tuple, user_lat, user_lon, >>> slice_tags, user_point, radius, map_ >>> ) """ _, line = iter_tuple x = line[user_lat] y = line[user_lon] tags_formated = _format_tags(line, slice_tags) folium.Circle( radius=radius, location=[x, y], popup=tags_formated, color=user_point, fill=False ).add_to(map_)
[docs]def plot_points( move_data: DataFrame, user_lat: str = LATITUDE, user_lon: str = LONGITUDE, user_point: str = USER_POINT, radius: float = 2, base_map: Map | None = None, slice_tags: list | None = None, tiles: str = TILES[0], save_as_html: bool = False, filename: str = 'points.html' ) -> Map: """ Generates a folium map with the trajectories plots and a point. Parameters ---------- move_data: Dataframe Trajectory data. user_lat: str, optional Latitude column name, by default LATITUDE. user_lon: str, optional Longitude column name, by default LONGITUDE. user_point: str, optional The point color, by default USER_POINT. radius: float, optional radius size, by default 2. sort:Boolean, optional If True the data will be sorted, by default False. base_map: Folium map, optional A folium map to plot the trajectories. If None a map will be created, by default None. slice_tags: optional, by default None. tiles: str, optional, by default TILES[0] The map type. save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False. filename : str, optional Represents the file name of new file .html, by default 'points.html'. Returns ------- Map A folium map Examples -------- >>> from pymove.visualization.folium import plot_points >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> plot_points(move_df) """ if slice_tags is None: slice_tags = list(move_data.columns) # If not have a map a map is create with mean to lat and lon if not base_map: initial_lat = move_data[user_lat].mean() initial_lon = move_data[user_lon].mean() base_map = create_base_map( move_data=move_data, lat_origin=initial_lat, lon_origin=initial_lon, tile=tiles ) for row in move_data.iterrows(): _circle_maker( row, user_lat, user_lon, slice_tags, user_point, radius, base_map ) if save_as_html: base_map.save(outfile=filename) return base_map
[docs]def plot_poi( move_data: DataFrame, poi_lat: str = LATITUDE, poi_lon: str = LONGITUDE, poi_point: str = POI_POINT, radius: float = 2, base_map: Map | None = None, slice_tags: list | None = None, tiles: str = TILES[0], save_as_html: bool = False, filename: str = 'pois.html' ) -> Map: """ Receives a MoveDataFrame and returns a folium map with poi points. Parameters ---------- move_data: DataFrame Trajectory input data poi_lat: str, optional Latitude column name, by default LATITUDE. poi_lon: str, optional Longitude column name, by default LONGITUDE. poi_point: str, optional Poi point color, by default POI_POINT. radius: float, optional radius size, by default 2. base_map: Folium map, optional A folium map to plot. If None a map. If None a map will be created, by default None. slice_tags: optional, by default None. tiles: str, optional, by default TILES[0] The map type. save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False. filename : str, optional Represents the file name of new file .html, by default 'pois.html'. Returns ------- folium.folium.Map. Represents a folium map with visualization. Examples -------- >>> from pymove.visualization.folium import plot_poi >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> plot_poi(move_df) """ return plot_points( move_data, user_lat=poi_lat, user_lon=poi_lon, user_point=poi_point, radius=radius, base_map=base_map, slice_tags=slice_tags, tiles=tiles, save_as_html=save_as_html, filename=filename )
[docs]def plot_event( move_data: DataFrame, event_lat: str = LATITUDE, event_lon: str = LONGITUDE, event_point: str = EVENT_POINT, radius: float = 2, base_map: Map | None = None, slice_tags: list | None = None, tiles: str = TILES[0], save_as_html: bool = False, filename: str = 'events.html' ) -> Map: """ Receives a MoveDataFrame and returns a folium map with events. Parameters ---------- move_data: DataFrame Trajectory input data event_lat: str, optional Latitude column name, by default LATITUDE. event_lon: str, optional Longitude column name, by default LONGITUDE. event_point: str, optional Event color, by default EVENT_POI radius: float, optional radius size, by default 2. base_map: Folium map, optional A folium map to plot. If None a map. If None a map will be created, by default None. tiles: str, optional, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False. filename : str, optional Represents the file name of new file .html, by default 'events.html'. Returns ------- A folium map. Examples -------- >>> from pymove.visualization.folium import plot_event >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> plot_event(move_df) """ return plot_points( move_data, user_lat=event_lat, user_lon=event_lon, user_point=event_point, radius=radius, base_map=base_map, slice_tags=slice_tags, tiles=tiles, save_as_html=save_as_html, filename=filename )
def _create_geojson_features_line( move_data: DataFrame, label_lat: str = LATITUDE, label_lon: str = LONGITUDE, label_datetime: str = DATETIME ) -> list: """ Create geojson features. Parameters ---------- move_data: DataFrame. Input trajectory data. label_datetime: str, optional date_time colum label, by default DATETIME. label_lat: str, optional latitude column label, by default LATITUDE. label_lon: str, optional longitude column label, by default LONGITUDE. Returns ------- list GeoJSON features. Examples -------- >>> from pymove.visualization.folium import _create_geojson_features_line >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> _create_geojson_features_line(move_df) [ { "type":"Feature", "geometry":{ "type":"Linestr", "coordinates":[ [ 116.319236, 39.984094 ], [ 116.319322, 39.984198 ] ] }, "properties":{ "times":[ "2008-10-23T05:53:05", "2008-10-23T05:53:06" ], "popup":"lat: 39.984094<br>lon: 116.319236<br> \ datetime: 2008-10-23 05:53:05<br>id: 1", "style":{ "color":"red", "icon":"circle", "iconstyle":{ "color":"red", "weight":4 } } } }, ... ] """ features = [] row_iterator = move_data.iterrows() _, last = next(row_iterator) columns = move_data.columns for i, row in progress_bar( row_iterator, total=move_data.shape[0], desc='Generating GeoJSon' ): last_time = last[label_datetime].strftime('%Y-%m-%dT%H:%M:%S') next_time = row[label_datetime].strftime('%Y-%m-%dT%H:%M:%S') popup_list = [i + ': ' + str(last[i]) for i in columns] popup1 = '<br>'.join(popup_list) feature = { 'type': 'Feature', 'geometry': { 'type': 'Linestr', 'coordinates': [ [last[label_lon], last[label_lat]], [row[label_lon], row[label_lat]] ] }, 'properties': { 'times': [last_time, next_time], 'popup': popup1, 'style': { 'color': 'red', 'icon': 'circle', 'iconstyle': { 'color': 'red', 'weight': 4 } } } } _, last = i, row features.append(feature) return features
[docs]def plot_traj_timestamp_geo_json( move_data: DataFrame, label_lat: str = LATITUDE, label_lon: str = LONGITUDE, label_datetime: str = DATETIME, tiles: str = TILES[0], save_as_html: bool = False, filename: str = 'events.html' ) -> Map: """ Plot trajectories wit geo_json. Parameters ---------- move_data: DataFrame. Input trajectory data. label_datetime: str, optional, by default DATETIME. date_time column label. label_lat: str, optional, by default LATITUDE. latitude column label. label_lon: str, optional, by default LONGITUDE. longitude column label. tiles: str, optional map tiles, by default TILES[0] save_as_html : bool, optional Represents if want save this visualization in a new file .html, by default False. filename : str, optional Represents the file name of new file .html, by default 'events.html'. Returns ------- Map A folium map. Examples -------- >>> from pymove.visualization.folium import plot_traj_timestamp_geo_json >>> move_df.head() lat lon datetime id 0 39.984094 116.319236 2008-10-23 05:53:05 1 1 39.984198 116.319322 2008-10-23 05:53:06 1 2 39.984224 116.319402 2008-10-23 05:53:11 1 3 39.984211 116.319389 2008-10-23 05:53:16 1 4 39.984217 116.319422 2008-10-23 05:53:21 1 >>> plot_traj_timestamp_geo_json(move_df) """ features = _create_geojson_features_line( move_data, label_lat=label_lat, label_lon=label_lon, label_datetime=label_datetime ) base_map = create_base_map( move_data=move_data, lat_origin=move_data[label_lat].mean(), lon_origin=move_data[label_lon].mean(), tile=tiles ) plugins.TimestampedGeoJson( { 'type': 'FeatureCollection', 'features': features, }, period='PT1M', add_last_point=True ).add_to(base_map) if save_as_html: base_map.save(filename) return base_map